自定义命令需继承 symfony command 并注册到 webman/console 系统,命名空间为 app\command、类名以 command 结尾、设置 $defaultname;执行时需手动引入 bootstrap.php 才能使用 config() 或 db::。

php webman 命令本身不直接执行 PHP 脚本文件,而是交由 webman/console 组件统一调度——所有自定义命令必须继承 Symfony\Component\Console\Command\Command,注册为 console 命令才能被识别和运行。裸写一个 .php 文件放在 scripts/ 下,php webman 是完全看不到的。
如何让自定义命令出现在 php webman 列表里
核心是两步:生成命令类 + 正确命名 + 注册到 console 系统。
-
php webman make:command db:config会生成app\command\DbConfigCommand.php,注意命名空间必须是app\command - 类名必须以
Command结尾(如DbConfigCommand),且protected static $defaultName必须设为唯一命令标识(如'db:config') - 不需要手动注册:webman 启动时自动扫描
app/command目录下所有*Command.php文件并加载 - 命令名中冒号
:仅作语义分组,无特殊语法含义;但建议保持group:action风格,便于后续扩展
为什么 execute() 里用不了 config() 或 Db::
常见现象:命令能跑起来,但一调 config('database') 就报 Call to undefined function config() 或数据库连接失败。
- 根本原因:命令启动时未加载 webman 的支持层,
support/bootstrap.php没被执行 - 解决方案:在
execute()开头显式引入——require_once base_path().'/support/bootstrap.php'; - 更稳妥做法:把
bootstrap.php加到命令基类的__construct()或initialize()中(如果项目有统一基类) - 注意:不要在
configure()阶段调用config(),此时框架尚未初始化,会出错
php webman xxx 和 php scripts/xxx.php 怎么选
二者定位完全不同,不是“哪个更好”,而是“解决什么问题”。
- 用
php webman xxx:需要访问完整框架上下文(路由、中间件、配置、数据库、缓存、日志等),适合长期维护、多人协作、需复用业务逻辑的运维任务(如数据迁移、定时统计、权限同步) - 用
php scripts/xxx.php:纯临时脚本,只依赖 autoload 和少量核心类(如Db),无需启动 console 生命周期。适合一次性数据修复、导入导出、调试验证 - 性能差异极小,但命令方式自带参数解析、帮助文档、颜色输出、退出码规范,
scripts/方式则完全自由,也更容易误删或遗忘 - 部署时注意:
scripts/下的文件不会被webman plugin:export或打包命令包含,而app/command/下的会自动纳入
参数、选项、交互输入怎么写才不踩坑
别硬编码解析 $argv,用 Symfony Console 提供的标准机制。
- 必填参数:在
configure()里用$this->addArgument('name', InputArgument::REQUIRED),获取时用$input->getArgument('name') - 可选参数/选项:用
InputArgument::OPTIONAL或InputOption::VALUE_OPTIONAL,避免getArgument()返回null导致空指针 - 布尔开关(如
--force):用InputOption::VALUE_NONE,判断用$input->getOption('force')(返回true或false) - 交互式输入(如确认删除):用
$helper = $this->getHelper('question');+ConfirmationQuestion,别用fgets(STDIN)—— 在 CI/CD 环境下会卡死 - 输出带格式:用
$output->writeln('<info>Done.</info>'),支持info、comment、error、fg=red等,比echo更健壮
execute() 里启了一个 Worker 子进程,没做 pcntl_signal 处理,Ctrl+C 时主进程退出但子进程还在跑;又或者用了协程但没配对 go()/chan,导致命令卡住不返回。这些细节,比写个 for 循环难得多。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











