在hyperf3.1中快速开发可复用cli命令:1. 用gen:command生成骨架;2. 手动补全configure()中parent::configure()调用;3. 在handle()中校验参数类型;4. 依赖注入仅限构造函数声明,业务逻辑必须在handle()执行;5. 用@listener注解注册事件监听器;6. 通过commands.php配置别名。

面试官问你如何在Hyperf3.1中快速开发一个可复用、带参数校验、支持事件监听的CLI命令,而不是只写个echo“Hello World”就交差。
创建基础命令类
执行命令生成骨架文件:php bin/hyperf.php gen:command UserSyncCommand。
这一步会自动在app/Command/目录下生成UserSyncCommand.php,并完成命名空间、继承关系和注解注册,省去手动写#[Command]和parent::__construct()的重复劳动。
生成后立刻检查configure()方法是否被正确覆盖——如果没被覆盖,说明gen:command未识别到Hyperf 3.1的最新模板,需手动补全parent::configure()调用,否则php bin/hyperf.php list里看不到该命令。
添加必填参数与类型约束
在configure()方法内添加参数声明:
$this->addArgument('user-id', InputArgument::REQUIRED, '用户ID,必须为正整数');
$this->addOption('force', 'f', InputOption::VALUE_NONE, '强制同步,跳过状态校验');
注意:Hyperf 3.1默认不校验参数类型,【user-id参数传入字符串或负数不会自动报错】,必须在handle()中手动校验,否则可能引发后续数据库查询异常。
校验逻辑示例(直接写进handle()):
$userId = $this->input->getArgument('user-id'); if (!is_numeric($userId) || (int)$userId error('user-id 必须是大于0的整数'); return 1; }
注入依赖并调用业务服务
在构造函数中声明依赖,例如用户同步服务:
public function __construct(protected UserService $userService, protected ContainerInterface $container) { parent::__construct('user:sync'); }
Hyperf 3.1的Command类支持容器自动注入,但【不能在构造函数里调用业务方法】,因为此时命令尚未初始化完成,$this->input等属性还未绑定,会导致Call to a member function getArgument() on null错误。
所有输入解析和业务逻辑必须严格放在handle()方法内执行。
触发事件并监听响应
方法一:手动分发事件
在handle()末尾添加:
$this->eventDispatcher->dispatch(new UserSyncStarted($userId));
方法二:使用@Listener注解绑定监听器(推荐)
新建监听器类app/Listener/UserSyncCompletedListener.php,内容为:
#[Listener] class UserSyncCompletedListener implements ListenerInterface { public function listen(): array { return [UserSyncFinished::class]; } public function process(object $event) { $this->logger->info('用户同步完成,ID:'.$event->userId); } }
监听器类无需手动注册,Hyperf 3.1启动时通过AnnotationCollector自动扫描#[Listener]并绑定事件映射关系。
配置命令别名与描述信息
第一步:打开config/autoload/commands.php,确认该文件存在且已启用(Hyperf 3.1默认启用)。
第二步:在return []数组中追加:
'user:sync' => [ 'alias' => ['sync:user', 'us'], 'description' => '同步指定用户数据至第三方系统', ],
第三步:执行php bin/hyperf.php list验证别名生效——此时输入php bin/hyperf.php sync:user 123或php bin/hyperf.php us 123均可触发同一命令。
注意:别名仅在commands.php中配置才有效,configure()里的setDescription()只影响list输出的描述文字,不影响别名功能。











