Laravel自定义Artisan命令需先用php artisan make:command生成,Laravel 8+默认自动发现(要求类在app/Console/Commands/下、继承Command、有有效$signature),否则需在Kernel.php中手动注册;报错“Command not defined”主因是未加载,应检查autoload、$signature、命名空间及php artisan list输出。

如何生成并注册一个 Laravel Artisan 自定义命令
Artisan 命令不是写完就能直接运行的,必须先通过 php artisan make:command 生成骨架,再手动注册(Laravel 8+ 默认自动发现,但需确认配置)。
- 运行
php artisan make:command SendWeeklyReport生成命令类,位于app/Console/Commands/SendWeeklyReport.php - Laravel 8+ 默认启用命令自动发现,只要该类在
app/Console/Commands/下、继承Illuminate\Console\Command、且有$signature属性,就会被识别 - 若使用旧版本或禁用了自动发现,需在
app/Console/Kernel.php的$commands数组中显式添加:protected $commands = [ Commands\SendWeeklyReport::class, ]; - 确保类中的
$signature不含空格或非法字符(如send:weekly-report合法,send: weekly report会报错)
为什么 php artisan my:command 报错 “Command ‘my:command’ is not defined”
最常见原因是命令未被加载——不是代码写错了,而是没进 Autoloader 或未满足自动发现条件。
- 检查命令类是否已执行
composer dump-autoload(尤其在手动移动文件或修改命名空间后) - 确认
$signature属性已正确定义,且不为null或空字符串;Artisan 依赖它做路由匹配 - 检查命名空间是否为
App\Console\Commands(或与composer.json中的 autoload 配置一致),否则dump-autoload不会扫描到 - 运行
php artisan list,看命令是否出现在输出中;没出现就说明根本没注册成功
如何在自定义命令中安全调用 Eloquent 和 DB 操作
Artisan 命令默认运行在 console 环境下,Eloquent 可用,但要注意连接和事务边界。
- 直接使用模型没问题:
use App\Models\User; // ... $activeUsers = User::where('active', true)->get(); - 避免在循环中频繁调用
save(),改用upsert()或DB::transaction()包裹批量操作 - 注意
DB::connection('mysql')和DB::connection('pgsql')在不同环境可能行为不一致,建议统一走模型或显式指定连接 - 如果命令需长时间运行(如处理十万条记录),加上
$this->line("Processed {$i} records...");并调用sleep(0.01)防止内存溢出
如何传参、选项并做参数校验
$signature 字符串不只是“起个名字”,它定义了完整的 CLI 接口契约。
- 必需参数写成
{user_id},可选参数加问号:{user_id?},带默认值写成{user_id=1} - 选项用
--force或-f形式,定义为{--force : Force run without confirmation} - 在
handle()中用$this->argument('user_id')和$this->option('force')获取,别直接读$argv - 校验逻辑建议放在
handle()开头:if (!$this->option('force') && !$this->confirm('Continue?')) { return self::FAILURE; }
APP_ENV=console 和 DB_CONNECTION 配置错位会导致命令能启动却查不到数据。










