對於Yii2而言,命令行應用和網頁應用基本是相似的,添加一個命令行命令的過程,和添加一個action是同樣的。網頁應用的入口文件是web目錄下的index.php,而命令行應用的入口文件在應用根目錄下的yii(windows系統對應的是yii.bat),典型的入口文件以下:php
#!/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。由於命令行應用和網頁應用的應用場景不一樣,所依賴的模塊和組建也會差異很大,所以用不一樣的配置文件,儘可能減小初始化沒必要要的組建所帶來的性能損失。linux
命令行應用一樣遵循MVC結構,不一樣的是V一般沒有啦,通常只有Controller和Model。每一個Controller文件能夠有多個action,調用方式和網頁應用相似,例如:web
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數據庫
###調用bootstrap
####同步調用 php提供了好多調用命令行程序的方式,如exec,system,popen,等等。須要調用命令行程序的適合,只要組裝相應地命令就好了。如 exec("php xxx/default/index abc"),就是調用xxx模塊下地default控制器的index方法,參數傳的是abc ####異步調用 須要涉及到命令行程序的場景,一般是執行時間較長的任務,好比發送郵件(若是郵件服務器繁忙,經常形成同步調用的狀況下等待時間過長而30秒超時),爬蟲抓取,或者執行一些大批量的數據庫讀寫操做。這種場景下,網頁程序只負責激活這個命令行程序,讓其繼續執行,頁面不等待命令行執行結束,就返回了。代碼以下:windows
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服務器充當的是一個命令調度的角色,以多進程的方式,調用不一樣的命令行程序。服務器