注册自定义artisan命令需手动创建类并显式注册,类须继承illuminate\console\command、实现handle()方法,$signature不能为空或重复;输出依赖cli上下文,非cli环境需用artisan::call()调用;参数选项格式须严格,大数据处理应分块避免内存溢出。

怎么注册一个自定义 Artisan 命令
必须手动在 app/Console/Commands/ 下创建类,并在 app/Console/Kernel.php 的 $commands 数组里显式注册,Laravel 不会自动扫描或加载。
- 命令类需继承
Illuminate\Console\Command,且必须实现handle()方法(否则运行时报Method handle does not exist) - 类名末尾建议带
Command后缀(如SendWeeklyReportCommand),否则php artisan list可能不显示描述 - 别漏掉
protected $signature = 'report:send';—— 这是命令的唯一标识,空值或重复会导致Command already registered
为什么 handle() 里用 $this->info() 没输出
常见于在队列任务或测试环境中调用命令时:Artisan 命令的 I/O 绑定依赖 Application 实例的当前终端上下文,直接 new 实例或在非 CLI 环境中调用,$this->output 是 null。
- 正确触发方式只有
php artisan report:send或Artisan::call('report:send') - 若要在其他地方复用逻辑,把核心逻辑抽到 Service 类里,
handle()只负责参数解析和调用,别塞业务代码 -
$this->line()、$this->error()等方法底层走的是 Symfony Console 的 OutputInterface,不是 echo,所以不能靠浏览器看输出
如何传参和选项并避免解析失败
$signature 字符串写法直接影响参数是否被识别,空格、冒号、等号位置错一位就报 Not enough arguments 或静默忽略。
- 必需参数:
user:import {file}→ 运行时必须跟值:php artisan user:import users.csv - 可选参数:
user:import {file?}→{file? : default.csv}支持默认值 - 选项(带 --):
{--force}(布尔)、{--env=}(需值)、{--env=production}(带默认) - 别写
{--force=true}—— 这会被当成字符串值,实际想传布尔就用--force不带等号
命令执行慢或卡住,怎么排查
Artisan 命令默认在主进程同步执行,没超时控制,也没自动重试,一旦底层调用阻塞(比如 HTTP 请求、DB 锁、大文件读取),整个命令就挂住。
- 加
set_time_limit(0)在handle()开头?别——PHP CLI 默认不限时,加了反而可能干扰 - 用
DB::transaction()包裹写操作,但记得捕获QueryException,否则异常后事务不回滚,下次运行可能因数据状态异常失败 - 大量数据处理务必分块:
User::query()->chunkById(100, function ($users) { ... }),别用get()全查进内存 - 日志写到
storage/logs/laravel.log比info()输出更可靠,尤其后台运行时
php artisan clear:cache 因权限问题静默失败,然后三天后才发现缓存没清。









