Yii2 Day 10 创建命令行应用

创建

入口文件

对于Yii2而言,命令行应用和网页应用基本是类似的,添加一个命令行命令的过程,和添加一个action是一样的。网页应用的入口文件是web目录下的index.php,而命令行应用的入口文件在应用根目录下的yii(windows系统对应的是yii.bat),典型的入口文件如下:

#!/usr/bin/env php
<?php
/**
 * Yii console bootstrap file.
 *
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

defined('YII_DEBUG') or define('YII_DEBUG', true);

// fcgi doesn't have STDIN and STDOUT defined by default
defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));

require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');

$config = require(__DIR__ . '/config/console.php');

$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);

与web相比,有两个不同的地方值得注意,一个是定义了标准输入输出,另外一个是引入了console.php配置文件,相对的网页应用引入的是web.php。因为命令行应用和网页应用的应用场景不同,所依赖的模块和组建也会差别很大,因此用不同的配置文件,尽量减少初始化不必要的组建所带来的性能损失。

文件结构

命令行应用同样遵循MVC结构,不同的是V通常没有啦,一般只有Controller和Model。每个Controller文件可以有多个action,调用方式和网页应用类似,例如:

class ExampleController extends \yii\console\Controller
{
    // 调用命令 "yii example/create test", 这里的$name会被赋值为test
    public function actionCreate($name) { ... }

    // 调用命令 "yii example/index city id" $category=city,$order=id
    public function actionIndex($category, $order = 'name') { ... }

    // 调用命令 "yii example/add test", 其中,$name = ['test']
    // 调用命令 "yii example/add test1,test2" 其中,$name = ['test1', 'test2']
    public function actionAdd(array $name) { ... }
}

####模块内命令 为了简单耦合度,比较好的选择是讲命令行程序都封装到各个模块,而不是全部放在应用根目录下的commands目录下。那么怎么让命令行的各个controller也分部到各个模块里呢?关键就在于模块类的controllerNamespace这个成员变量。网页应用的模块,这个变量通过被设置成app\模块id\controllers,因此,如果是命令行的controller,通常放到模块内的commands目录下,因此这个命名空间就需要赋值成app\模块id\commands

###调用

####同步调用 php提供了好多调用命令行程序的方式,如exec,system,popen,等等。需要调用命令行程序的适合,只要组装相应地命令就行了。如 exec("php xxx/default/index abc"),就是调用xxx模块下地default控制器的index方法,参数传的是abc ####异步调用 需要涉及到命令行程序的场景,通常是执行时间较长的任务,比如发送邮件(如果邮件服务器繁忙,常常造成同步调用的情况下等待时间过长而30秒超时),爬虫抓取,或者执行一些大批量的数据库读写操作。这种场景下,网页程序只负责激活这个命令行程序,让其继续执行,页面不等待命令行执行结束,就返回了。代码如下:

if (substr(php_uname(), 0, 7) == "Windows")
{
    pclose(popen("start /B ". $cmd, "r"));
}
else 
{
    $php = 'php';
    exec($php.' '.  $cmd . " > /dev/null &");    
}

windows服务器和linux服务器有着不同的处理方式。 ####socket调用 如果命令行程序和网页程序不在一个服务器上,远程调用,那么将命令行程序封装成socket服务,启动之后常驻内存中,网页端通过socket消息的方式,告诉socket服务程序执行相应地命令行程序,同样这里需要使用上一节提到的异步调用方式,socket服务器充当的是一个命令调度的角色,以多进程的方式,调用不同的命令行程序。

转载于:https://my.oschina.net/u/248080/blog/480327

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值