在 $signature 中声明短选项和长选项需显式写出:{--force : 强制执行 : -f}(laravel 9.2+)支持缩写,{--timeout=} 表示接收值,{--force} 为布尔开关;等号不可省略,否则类型错位导致报错或传参失效。

怎么在 $signature 里声明短选项和长选项
短选项(如 -f)和长选项(如 --force)必须在命令类的 $signature 属性中显式写出,不能靠 configure() 补充。Laravel 会自动解析它们并绑定到后续的 $this->option() 调用。
写法很简单:
-
{--force}:布尔开关,支持--force或-f(如果加了缩写) -
{--timeout=}:必填值,支持--timeout=30或-t 30 -
{--log-level= : 日志级别}:带描述的可选值,--log-level用默认值,--log-level=debug覆盖默认值 - 缩写用冒号后接单字母:
{--force : 强制执行 : -f}—— 注意这是 Laravel 9.2+ 的语法,旧版本不支持,得回退到addOption()
别漏掉等号:{--timeout} 是布尔型,{--timeout=} 才是接收值的;类型错位会导致传参被忽略或报错。
为什么 $this->option('xxx') 返回 null 而不是默认值
当选项定义为 {--env=local},你以为没传 --env 就该返回 "local",但实际是 null —— 因为 Laravel 只在「完全未提供该选项」时才用默认值;一旦写了 --env 却没给值(比如只输 php artisan foo --env),它就认为你明确传了个空值,返回 null。
安全读取方式:
- 判断是否设置了:
$this->option('force') !== null(不能用isset(),因为布尔 false 也会被判定为未设置) - 取值带兜底:
$timeout = $this->option('timeout') ?? 30 - 布尔选项直接当条件用:
if ($this->option('force')) { ... },不用=== true
为什么 --env 在自定义命令里读不到
$this->option('env') 永远是 null,因为 --env 是 Artisan 启动阶段就消费的参数,用于加载 .env 和环境配置文件,它根本不会透传进你的命令实例。
真正起作用的是启动前的环境变量,比如:
APP_ENV=staging php artisan foo-
php artisan foo --env=staging这种写法对你的命令逻辑无效
如果真要动态切环境,得自己定义 {--app-env=},然后手动调 App::environment($value) 或重载配置 —— 但极不推荐,容易破坏容器状态和配置缓存。
短选项连写(如 -vf)为什么不生效
Laravel 默认不支持连写短选项,-vf 不会被拆成 -v 和 -f,而是当作一个叫 vf 的未知选项报错。
原因在于 Symfony Console 底层默认关闭了 setParseOptionsFirst(true),而 Laravel 没有启用它。
能做的只有两种:
- 老老实实用分开写:
php artisan foo -v -f - 或者在
configure()中用$this->addOption('verbose', 'v', InputOption::VALUE_NONE)+$this->addOption('force', 'f', InputOption::VALUE_NONE),再配合$this->option('verbose')和$this->option('force')分别判断
别指望靠 $signature 一行搞定连写,它不在 Laravel 的设计范围内。











