必须注册、继承command、返回command::success/failure;类名以command结尾,置于src/command/;configure()中显式声明参数选项;布尔选项判null需用===true;依赖须构造注入,禁用getcontainer()。

直接能用的 Symfony Console 命令,不是写个 PHP 文件扔进 bin/ 就行——必须注册、必须继承 Command、返回值必须是 Command::SUCCESS 或 Command::FAILURE,否则测试断言会失败,CI 里直接红。
命令类怎么命名和放哪?
类名必须以 Command 结尾,比如 UserImportCommand;文件路径默认是 src/Command/(不是强制,但自动加载和工具扫描都按这个约定来);类要继承 Symfony\Component\Console\Command\Command;static $defaultName 里用冒号分层,别写成短横线(app-user-import 是错的,得是 app:user:import)。
参数和选项为什么总是读不到?
常见错误不是代码写错,而是没在 configure() 里显式声明:
- 必需位置参数:必须调用
$this->addArgument('env', InputArgument::REQUIRED),否则$input->getArgument('env')永远是null - 布尔选项(如
--dry-run)默认值是null,不是false;判断时得写$input->getOption('dry-run') === true,别用empty()或! - 带默认值的选项,第 5 个参数才是默认值:
$this->addOption('timeout', null, InputOption::VALUE_REQUIRED, '', 30);漏掉第 4 个空字符串说明,help 文本里就看不到描述 - 含空格的参数(如用户名
"John Doe")必须加引号传入,shell 不加引号只会截断到第一个空格
依赖注入和数据库操作怎么写才安全?
CLI 环境没有请求上下文,硬调 RequestStack 或 SessionInterface 会直接抛 LogicException:
- 依赖必须走构造函数注入,比如
public function __construct(private EntityManagerInterface $em);禁用$this->getContainer()—— 这是 Symfony 4.0 前的写法,已弃用 - 数据库操作优先用
EntityManagerInterface类型提示,别用字符串 ID(如doctrine.orm.default_entity_manager),容器里根本没这服务 -
execute()返回值必须是Command::SUCCESS或Command::FAILURE,别直接return 0或1,否则单元测试里的assertCommandIsSuccessful()会失败
命令注册不生效?检查这三个地方
写了类、放对位置、继承了 Command,但 php bin/console list 里还是看不到——大概率卡在这三处:
-
bin/console入口文件里漏了$application->add(new UserImportCommand());独立使用组件时必须手动add(),不会自动扫描 - 类名没以
Command结尾,Doctrine、MakerBundle 等工具扫描时直接跳过 - 自动加载没覆盖到
src/Command/,检查composer.json的"autoload": {"psr-4": {...}}是否包含该路径
最常被忽略的是布尔选项的 null 初始态和构造函数注入的强制性——这两个点一错,命令看似能跑,但在 CI 或用户真实使用中会静默失败或行为异常。











