yii 3.0 控制台命令需通过 psr-11 容器绑定并注册,类须继承 yiisoft/console/command、命名以 command 结尾、显式声明依赖,execute() 返回 int 状态码,参数须在 configure() 中声明,入口文件需正确配置 autoload 并加载 config/console.php。

在 Yii 3.0 中配置控制台命令,必须绕过已废弃的 ServiceLocator 和传统入口文件结构,直接通过 PSR-11 容器绑定控制器类并注册为可执行命令——否则运行时会报 Call to undefined method yii\console\Application::controllerMap() 或 Class not found 错误。
创建控制台命令类
在 src/Console/Command 目录下新建 PHP 文件,例如 SendNewsletterCommand.php;文件名必须以 Command 结尾,且类名需与文件名一致。
类必须继承 yiisoft/console/Command,不能用 Yii 2 的 yii\console\Controller;构造函数中所有依赖必须显式声明,例如 private MailerInterface $mailer。
定义 execute() 方法作为主逻辑入口,返回 int 状态码(0 表示成功,非 0 表示失败);不支持 actionXxx() 命名风格,也不再识别 public function actionSend() 这类写法。
注册命令到 DI 容器
打开 config/console.php,在 services 数组中添加命令类绑定:
SendNewsletterCommand::class => static fn() => new SendNewsletterCommand($container->get(MailerInterface::class))
注意:不能使用 Yii::createObject() 或匿名函数中直接 new 实例而不注入依赖——【容器未解析依赖就实例化会导致类型缺失错误】。
若命令需接收参数或选项,必须在 configure() 方法中调用 $this->addArgument() 或 $this->addOption() 显式声明;未声明的参数将被忽略,不会自动映射到方法参数。
配置 CLI 入口文件
第一步:确认项目根目录下存在可执行的 yii 文件(由 yiisoft/app 模板自动生成),且具备执行权限:chmod +x yii。
第二步:检查该文件首行是否为 #!/usr/bin/env php,且第二行是否包含 require __DIR__ . '/vendor/autoload.php';;若缺失,手动补全,否则 CLI 启动时无法加载类。
第三步:确保 config/console.php 被 yii 入口正确加载——它必须在 ApplicationFactory::create() 的配置参数中传入,而不是靠自动扫描发现。
这一步操作起来很简单,直接把文件拖进去就行。但漏掉任意一行,命令就会静默失败,终端无任何输出。
运行与调试命令
方法一:在项目根目录执行 ./yii send-newsletter --to=admin@example.com;命令名自动从类名 SendNewsletterCommand 转换为 kebab-case 格式。
方法二:若需调试依赖注入过程,在 execute() 开头插入 var_dump($this->mailer); exit;,然后运行命令观察输出;CLI 模式下 var_dump 不会格式化 HTML,输出是原始数组结构。
方法三:强制重新生成 DI 容器缓存(当修改了 config/console.php 后):执行 php vendor/bin/yii-dev clear-cache,否则旧绑定仍生效。











