创建CLI命令

Yii有一个好的命令行支持,允许创建可复用的控制台命令。控制台命令比创建web GUI更快。如果你需要为你的应用创建一些工具,可以被开发者或者管理使用,那么控制台命令就是很好的工具。

为了展示如何创建一个控制台命令,我们将会创建一个简单的命令,它会清理一些东西,例如assets和临时文件夹。

准备

按照官方指南http://www.yiiframework.com/doc-2.0/guide-start-installation.html的描述,使用Composer包管理器创建一个新的yii2-app-basic应用。

如何做…

执行如下过程来创建CLI命令:

  1. 使用如下代码创建commands/CleanController.php
  1. <?php
  2. namespace app\commands;
  3. use yii\console\Controller;
  4. use yii\helpers\FileHelper;
  5. /**
  6. * Removes content of assets and runtime directories.
  7. */
  8. class CleanController extends Controller
  9. {
  10. public $assetPaths = ['@app/web/assets'];
  11. public $runtimePaths = ['@runtime'];
  12. /**
  13. * Removes temporary assets.
  14. */
  15. public function actionAssets()
  16. {
  17. foreach ((array)$this->assetPaths as $path) {
  18. $this->cleanDir($path);
  19. }
  20. $this->stdout('Done' . PHP_EOL);
  21. }
  22. /**
  23. * Removes runtime content.
  24. */
  25. public function actionRuntime()
  26. {
  27. foreach ((array)$this->runtimePaths as $path) {
  28. $this->cleanDir($path);
  29. }
  30. $this->stdout('Done' . PHP_EOL);
  31. }
  32. private function cleanDir($dir)
  33. {
  34. $iterator = new
  35. \DirectoryIterator(\Yii::getAlias($dir));
  36. foreach($iterator as $sub) {
  37. if(!$sub->isDot() && $sub->isDir()) {
  38. $this->stdout('Removed ' . $sub->getPathname()
  39. . PHP_EOL);
  40. FileHelper::removeDirectory($sub->getPathname());
  41. }
  42. }
  43. }
  44. }
  1. 现在我们可以使用我们自己的控制台命令。只需要运行yii shell脚本。
  1. ./yii
  1. 查找自己的clean命令:
  1. This is Yii version 2.0.7.
  2. The following commands are available:
  3. - asset Allows you to combine...
  4. asset/compress Combines and compresses the asset...
  5. asset/template Creates template of configuration
  6. file...
  7. ...
  8. - clean Removes content of assets and
  9. runtime directories.
  10. clean/assets Removes temporary assets.
  11. clean/runtime Removes runtime content.
  12. - fixture Manages fixture data loading and
  13. unloading.
  14. fixture/load (default) Loads the specified fixture data.
  15. fixture/unload Unloads the specified fixtures.
  16. ...
  1. 运行asset清理:
  1. .yii clean/assets
  1. 查看处理报告:
  1. Removed /yii-book.app/web/assets/25f82b8a
  2. Removed /yii-book.app/web/assets/9b3b2888
  3. Removed /yii-book.app/web/assets/f4307424
  4. Done
  1. 如果你想在yii2-app-advanced应用中使用这个控制器,只需要指定自定义工作路径:
  1. return [
  2. 'id' => 'app-console',
  3. 'basePath' => dirname(__DIR__),
  4. 'bootstrap' => ['log'],
  5. 'controllerNamespace' => 'console\controllers',
  6. 'controllerMap' => [
  7. 'clean' => [
  8. 'class' => 'console\controllers\CleanController',
  9. 'assetPaths' => [
  10. '@backend/web/assets',
  11. '@frontend/web/assets',
  12. ],
  13. 'runtimePaths' => [
  14. '@backend/runtime',
  15. '@frontend/runtime',
  16. '@console/runtime',
  17. ],
  18. ],
  19. ],
  20. // ...
  21. ];

工作原理…

所有的控制台命令应该继承yii\console\Controller类。因为所有的控制器命令在yii\console\Application运行,而不是yii\web\Application,我们没有办法来决定@webroot的值。此外,在yii2-app-advanced模板中,默认情况下,我们有前端、后端和控制子目录。对于这个目的,我们创建可配置的公共数据,叫做assetPathsruntimePaths

控制台命令结构本身类似一个典型的控制器。我们定义几个动作,然后可以通过yii <console command>/<command action>来执行。

正如你所看到的,没有使用视图,所以我们可以把精力集中在编程任务上,而不需要设计、标记等等。此外,你需要提供一些有用的输出,这样用户就知道现在是什么情况。这可以通过简单的PHP echo语句来完成。

如果你的命令相对复杂,例如使用Yii构建的消息或者migrate,提供额外的描述是一个好的决定,说明可用的选项和动作。它可以通过复写getHelp方法完成:

  1. public function getHelp()
  2. {
  3. $out = "Clean command allows you to clean up various temporary data Yii and an application are generating.\n\n";
  4. return $out . parent::getHelp();
  5. }

运行如下命令:

  1. ./yii help clean

你会看到如下全部输出:

  1. DESCRIPTION
  2. Clean command allows you to clean up various temporary data Yii and
  3. an application are generating.
  4. Removes content of assets and runtime directories.
  5. SUB-COMMANDS
  6. - clean/assets Removes temporary assets.
  7. - clean/runtime Removes runtime content.

默认情况下,当我们运行shell命令时:

  1. ./yii

我们在输出列表中看到了所有命令的简化描述:

  1. - clean Removes content of assets and runtime directories.
  2. clean/assets Removes temporary assets.
  3. clean/runtime Removes runtime content.

这个描述将会从类和动作前边的注释中获取:

  1. /**
  2. * Removes content of assets and runtime directories.
  3. */
  4. class CleanController extends Controller
  5. {
  6. /**
  7. * Removes temporary assets.
  8. */
  9. public function actionAssets() { }
  10. * Removes runtime content.
  11. */
  12. public function actionRuntime() { }
  13. }

为你的类添加描述是可选的。你不用非得为你的CLI命令做这件事。

参考

  • 本章中的创建可复用控制器小节
  • 本章中制作可发布扩展小节