模板工程标准的控制台程序要素

(1)完整明确文字提示用户(并且使用红,绿,黄三种颜色标识提示文字;红色为错误相关,绿色为成功相关,黄色为进行中提示)

(2)告知用户运行进度(完成任务的一部分即显示进度条)

(3)如果需要用户做出选择,应该出现文本选择组件(通常为让用户选择yes还是no,或者使用1,2,3让用户做出选择)

(4)支持空执行(即使用事务回滚的方法,做出模拟执行,以避免在真正执行时出现错误,真正执行前会发现错误)

(5)支持无限次运行(使用缓存记录ID号的方法,若已经执行过则不再执行)

(6)命令行可以支持加参数

(7)核心业务逻辑应该被封装

例如:

/**
     * 山西永济基地的成品均改为标准件
     * 运行命令为./yii wms-handle/handle-piece-type-for-shanxi
     */
    public function actionHandlePieceTypeForShanxi(){
        //提示用户选择模拟更新还是真实更新
        if(Console::confirm("请选择真实更新还是模拟更新;模拟更新不会真正更新数据;[yes]为真实更新[no]为模拟更新")){
            $tip = Console::ansiFormat(PHP_EOL."正在轮询真实更新中",[Console::FG_GREEN]);
            Console::output("{$tip}");
            unset($tip);
            $is_update=true;
        }else{
            $tip = Console::ansiFormat(PHP_EOL."正在模拟更新中,不会真正更新",[Console::FG_RED]);
            Console::output("{$tip}");
            unset($tip);
            $is_update=false;
        }

        $wmsProductInSheetModels = \core\models\WmsProductInSheet::find()->where(['common_producer_info_id'=>14, 'piece_type'=>2])->orderBy(['id'=>SORT_ASC])->all();
        //设置进度条
        Console::startProgress(0, count($wmsProductInSheetModels));
        foreach ($wmsProductInSheetModels as $key => $wmsProductInSheetModel){
            $transtion = \Yii::$app->db->beginTransaction();
            try {
                //提示文字
                $tip = Console::ansiFormat(PHP_EOL . "正在处理成品入库单{$wmsProductInSheetModel->wms_product_in_sheet_number}", [Console::FG_YELLOW]);
                Console::output("{$tip}");
                unset($tip);
                //已经处理过则无需再次处理
                if (\Yii::$app->redis->sismember("in_sheet_number_updated_piece_type_for_shanxi", $wmsProductInSheetModel->wms_product_in_sheet_number)) {
                    throw new \yii\db\Exception(PHP_EOL . "成品入库单{$wmsProductInSheetModel->wms_product_in_sheet_number}已经更新过,无需再次更新");
                }

                //核心处理逻辑
                $updateHandler = $wmsProductInSheetModel->updatePieceTypeFrom2To1();
                if (!$updateHandler['status']){
                    throw new \yii\db\Exception($updateHandler['errmsg']);
                }else{
                    //提示文字
                    $tip = Console::ansiFormat(PHP_EOL . "正在处理成品入库单{$wmsProductInSheetModel->wms_product_in_sheet_number}成功", [Console::FG_GREEN]);
                    Console::output("{$tip}");
                    unset($tip);
                }

                //更新进度条
                Console::updateProgress($key + 1, count($wmsProductInSheetModels));
                //如果是模拟更新则回滚
                if (!$is_update) {
                    throw new \yii\db\Exception(PHP_EOL . "此次是模拟更新,不会真正更新,正在回滚到初始状态!");
                }
                $transtion->commit();
                //将已更新的入库单号添加到已更新队列中
                \Yii::$app->redis->sadd("in_sheet_number_updated_piece_type_for_shanxi", $wmsProductInSheetModel->wms_product_in_sheet_number);
            } catch (\yii\base\Exception $e) {
                $transtion->rollBack();
                $tip = Console::ansiFormat(PHP_EOL . $e->getMessage(), [Console::FG_RED]);
                Console::output("{$tip}");
                unset($tip);
            } catch (\yii\base\ErrorException $e) {
                $transtion->rollBack();
                $tip = Console::ansiFormat(PHP_EOL . $e->getMessage(), [Console::FG_RED]);
                Console::output("{$tip}");
                unset($tip);
            }
            unset($wmsProductInSheetModel);
        }
        unset($wmsProductInSheetModels);
        //设置进度条
        Console::endProgress();

        //成品出库单
        $wmsProductOutSheetModels = \core\models\WmsProductOutSheet::find()->where(['common_producer_info_id'=>14, 'piece_type'=>2])->orderBy(['id'=>SORT_ASC])->all();
        //设置进度条
        Console::startProgress(0, count($wmsProductOutSheetModels));
        foreach ($wmsProductOutSheetModels as $key => $wmsProductOutSheetModel){
            $transtion = \Yii::$app->db->beginTransaction();
            try {
                //提示文字
                $tip = Console::ansiFormat(PHP_EOL . "正在处理成品出库单{$wmsProductOutSheetModel->wms_product_out_sheet_number}", [Console::FG_YELLOW]);
                Console::output("{$tip}");
                unset($tip);
                //已经处理过则无需再次处理
                if (\Yii::$app->redis->sismember("in_sheet_number_updated_piece_type_for_shanxi", $wmsProductOutSheetModel->wms_product_out_sheet_number)) {
                    throw new \yii\db\Exception(PHP_EOL . "成品出库单{$wmsProductOutSheetModel->wms_product_out_sheet_number}已经更新过,无需再次更新");
                }

                //核心处理逻辑
                $updateHandler = $wmsProductOutSheetModel->updatePieceTypeFrom2To1();
                if (!$updateHandler['status']){
                    throw new \yii\db\Exception($updateHandler['errmsg']);
                }else{
                    //提示文字
                    $tip = Console::ansiFormat(PHP_EOL . "正在处理成品出库单{$wmsProductOutSheetModel->wms_product_out_sheet_number}成功", [Console::FG_GREEN]);
                    Console::output("{$tip}");
                    unset($tip);
                }

                //更新进度条
                Console::updateProgress($key + 1, count($wmsProductOutSheetModels));
                //如果是模拟更新则回滚
                if (!$is_update) {
                    throw new \yii\db\Exception(PHP_EOL . "此次是模拟更新,不会真正更新,正在回滚到初始状态!");
                }
                $transtion->commit();
                //将已更新的入库单号添加到已更新队列中
                \Yii::$app->redis->sadd("in_sheet_number_updated_piece_type_for_shanxi", $wmsProductOutSheetModel->wms_product_out_sheet_number);
            } catch (\yii\base\Exception $e) {
                $transtion->rollBack();
                $tip = Console::ansiFormat(PHP_EOL . $e->getMessage(), [Console::FG_RED]);
                Console::output("{$tip}");
                unset($tip);
            } catch (\yii\base\ErrorException $e) {
                $transtion->rollBack();
                $tip = Console::ansiFormat(PHP_EOL . $e->getMessage(), [Console::FG_RED]);
                Console::output("{$tip}");
                unset($tip);
            }
            unset($wmsProductOutSheetModel);
        }
        unset($wmsProductOutSheetModels);
        //设置进度条
        Console::endProgress();
    }

模拟执行的过程如下所示:

真实更新的过程如下:

Yii2控制台程序最佳实践的更多相关文章

  1. YII2 随笔 视图最佳实践

    yii\base\Controller::render(): 渲染一个 视图名 并使用一个 布局 返回到渲染结果. yii\base\Controller::renderPartial(): 渲染一个 ...

  2. 【转】优化Web程序的最佳实践

    自动排版有点乱,看着蛋疼,建议下载中文PDF版阅读或阅读英文原文. Yahoo!的Exceptional Performance团队为改善Web性能带来最佳实践.他们为此进行了 一系列的实验.开发了各 ...

  3. paip.java win程序迁移linux的最佳实践

    paip.java win程序迁移linux的最佳实践 1.class load路径的问题... windows哈第一的从calsses目录加载,,而linux优先从jar加载.. 特别的是修理了ja ...

  4. Windows Azure 安全最佳实践 - 第 6 部分:Azure 服务如何扩展应用程序安全性

    多种Windows Azure服务可以帮助您将应用程序安全性扩展到云. 有三种服务可提供多个提供程序之间的身份标识映射.内部部署数据中心间的连接和相互发送消息的应用程序功能(无论应用程序位于何处). ...

  5. Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(二)

    Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(一) 接上一篇 3. Nginx配置反向代理 3.1 cnetos 安装nginx 首先,我们需要在服务器上安装N ...

  6. Asp.NetCore程序发布到CentOs(含安装部署netcore)--最佳实践(一)

    环境 本地 win7 服务器:Virtual Box 上的Centos ssh工具: Xshell 文件传输: xftp 1.在本地创建asp.net core应用发布 1.1 使用Vs2017 新建 ...

  7. mpvue最佳实践 , 美团出的一个小程序框架

    看手机微信,看到说美团出了1个小程序框架,  mpvue 搜下来试试,看了网上的一个对比 ----------------- 以下为引用 我们对微信小程序.mpvue.WePY 这三个开发框架的主要能 ...

  8. Atitit. Gui控件and面板----程序快速启动区--最佳实践Launchy ObjectDock-o0g

    Atitit.  Gui控件and面板----程序快速启动区--最佳实践Launchy ObjectDock-o0g 两个方式::: 键盘式::先用热键呼叫出QS,然后开始输入程序中的部分字母,按En ...

  9. Javascript模块化编程(一)模块的写法最佳实践六、输入全局变量 独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。 为了在模块内部调用全局变量,必须显式地将其他变量输入模块。

    Javascript模块化编程,已经成为一个迫切的需求.理想情况下,开发者只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块但是,Javascript不是一种模块化编程语言,它不支持类clas ...

随机推荐

  1. num2cell

    num2cell的作用是把数值数组转换为cell数组. 最基本的用法是把数值数组的每个元素作为cell数组的元素,得到一个和原数组维度完全相同的cell数组,例如 >> A=magic(3 ...

  2. Mybatis学习总结(六)——高级映射(一对一,一对多,多对多)

    一.订单商品数据模型 1.数据库执行脚本 创建数据库表代码: /*Table structure for table `t_user` */ CREATE TABLE t_user ( id INT ...

  3. 洛谷 P2802 回家

    题目链接 https://www.luogu.org/problemnew/show/P2802 题目描述 小H在一个划分成了n*m个方格的长方形封锁线上. 每次他能向上下左右四个方向移动一格(当然小 ...

  4. Windows下安装RabbitMQ报错:unable to perform an operation on node时的解决方案

    在计算机领域中,想要程序完成各种功能,那么数据的交流和计算是非常重要的.现在已知的程序动作机制有协程,线程和进程. 在同一个程序中,或者说同一个进程中,数据的交流,传递,计算是非常的简单,只要把相关数 ...

  5. Docker存储卷(V18.X)

    简介 介绍 Docker的存储卷称之为volume,本质上容器上的一个或者多个目录,而这些目录绕过了联合文件系统,与宿主机中的目录或者其他容器目录进行了绑定关系,这种绑定关系可以看作Linux的mou ...

  6. WPF PasswordBox不支持绑定解决方法

    原文:WPF PasswordBox不支持绑定解决方法 PasswordBox的Password属性因为安全原因不支持直接绑定,可以使用依赖属性实现.直接插入代码 public class Passw ...

  7. JavaScript技巧总结和本地存储(二)

    离线检测 检测是否离线,html5为此定义了一个navigator.onLine属性,这个属性为true表示设备能上网,false表示离线,这个属性还有点兼容问题.因此单独使用这个属性不能确定网络是否 ...

  8. ajax相关问题

    1.contentType和dataType contentType 主要设置你发送给服务器的数据格式 dataType设置你收到服务器数据的格式(如text,json等),最常用的为json. 2. ...

  9. 使用Charles对iPhone进行Http(s)请求拦截(抓包)

    首先准备工具 1> Charles (下载对应操作系统的安装包进行安装,本文使用 macOS 进行演示) 2> iPhone (本文使用SE,系统版本:iOS 10) 开始 首先,对Cha ...

  10. semantic-ui 图片

    1.基础样式 方式一:因为图片是使用img标签,所以直接将class加载img标签中即可.不过要注意的是,class中要指定是ui image. 方式二:使用一个span或者div将img标签包裹,然 ...