Laravel 自带丰富的 Artisan 命令,可以执行数据库迁移、缓存清理和队列管理等操作。除了使用框架内置命令,开发者还可以创建项目专用命令,用于批量处理数据、同步业务状态和执行维护任务。
一、创建 Artisan 命令
在 Laravel 项目根目录执行:
php artisan make:command CheckOrders
执行后,Laravel 会生成文件:
app/Console/Commands/CheckOrders.php
不同 Laravel 版本的命令文件位置可能略有区别,应以项目实际目录为准。
二、配置命令名称和说明
打开 CheckOrders.php,编写以下内容:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class CheckOrders extends Command
{
protected $signature = 'orders:check';
protected $description = '检查待处理订单状态';
public function handle(): int
{
$this->info('开始检查订单状态');
$this->info('订单检查完成');
return self::SUCCESS;
}
}
其中:
signature定义命令名称。description设置命令说明。handle()是命令的主要执行方法。self::SUCCESS表示命令执行成功。
查看项目中的 Artisan 命令:
php artisan list
也可以直接搜索自定义命令:
php artisan help orders:check
三、执行自定义命令
运行刚刚创建的命令:
php artisan orders:check
预期输出:
开始检查订单状态
订单检查完成
如果命令没有出现在列表中,应检查命名空间、文件路径和项目当前 Laravel 版本的命令自动加载配置。
四、读取数据库数据
假设项目中已经存在 Order 模型,订单表包含 status 字段。可以在命令中查询待处理订单:
<?php
namespace App\Console\Commands;
use App\Models\Order;
use Illuminate\Console\Command;
class CheckOrders extends Command
{
protected $signature = 'orders:check';
protected $description = '检查待处理订单状态';
public function handle(): int
{
$orders = Order::query()
->where('status', 'pending')
->latest('id')
->get();
if ($orders->isEmpty()) {
$this->info('当前没有待处理订单');
return self::SUCCESS;
}
foreach ($orders as $order) {
$this->line("订单 {$order->id} 当前状态为 pending");
}
$this->info("共检查 {$orders->count()} 个订单");
return self::SUCCESS;
}
}
执行:
php artisan orders:check
如果数据量较大,不建议一次性使用 get() 加载全部记录,可以使用 chunkById():
Order::query()
->where('status', 'pending')
->chunkById(100, function ($orders) {
foreach ($orders as $order) {
$this->line("正在检查订单 {$order->id}");
}
});
这样可以减少单次查询占用的内存。
五、添加命令参数
如果希望指定订单 ID,可以在 $signature 中定义参数:
protected $signature = 'orders:check {orderId}';
在 handle() 中读取参数:
public function handle(): int
{
$orderId = $this->argument('orderId');
$order = Order::find($orderId);
if (!$order) {
$this->error("订单 {$orderId} 不存在");
return self::FAILURE;
}
$this->info("订单 {$order->id} 当前状态为 {$order->status}");
return self::SUCCESS;
}
执行命令:
php artisan orders:check 1001
如果订单不存在,命令会输出错误信息,并返回失败状态。
六、添加可选参数和选项
参数可以设置为可选:
protected $signature = 'orders:check {orderId?} {--status=pending}';
这里的 orderId 可以不传,--status 默认值为 pending。
读取参数和选项:
public function handle(): int
{
$orderId = $this->argument('orderId');
$status = $this->option('status');
$query = Order::query()
->where('status', $status);
if ($orderId) {
$query->whereKey($orderId);
}
$orders = $query->get();
$this->info("共找到 {$orders->count()} 个状态为 {$status} 的订单");
return self::SUCCESS;
}
执行示例:
php artisan orders:check
php artisan orders:check 1001 --status=paid
七、使用交互式输入
Artisan 支持在命令执行时询问用户:
public function handle(): int
{
$status = $this->choice(
'请选择要检查的订单状态',
['pending', 'paid', 'cancelled'],
0
);
$count = Order::query()
->where('status', $status)
->count();
$this->info("状态为 {$status} 的订单共有 {$count} 个");
return self::SUCCESS;
}
如果命令需要在计划任务或自动化脚本中执行,建议优先使用参数和选项,避免命令等待人工输入。
八、为批量操作增加确认提示
涉及修改或删除数据时,可以增加确认提示:
protected $signature = 'orders:close {--force : 跳过确认提示}';
public function handle(): int
{
if (!$this->option('force')) {
if (!$this->confirm('确定要关闭所有待处理订单吗?')) {
$this->warn('操作已取消');
return self::SUCCESS;
}
}
Order::query()
->where('status', 'pending')
->update([
'status' => 'closed',
]);
$this->info('待处理订单已关闭');
return self::SUCCESS;
}
自动化执行时,可以使用:
php artisan orders:close --force
使用 --force 前,应确认命令筛选条件和执行环境正确,避免误修改正式数据。
九、使用计划任务执行命令
如果需要定期执行自定义命令,可以将其加入 Laravel 的计划任务配置。
常见写法如下:
use Illuminate\Support\Facades\Schedule;
Schedule::command('orders:check')
->hourly();
也可以每天执行:
Schedule::command('orders:check')
->dailyAt('02:00');
计划任务本身还需要由服务器定期调用 Laravel 的调度入口。传统配置通常使用:
* * * * * cd /var/www/example && php artisan schedule:run >> /dev/null 2>&1
项目路径应替换为实际 Laravel 项目目录。
十、常见问题
Artisan 命令没有显示怎么办?
检查命令文件是否位于项目约定目录,命名空间是否正确,并执行:
composer dump-autoload
然后再次运行:
php artisan list
命令执行超时怎么办?
检查是否一次性加载了过多数据。可以改用 chunkById(),并减少单次处理数量。
如何记录命令执行日志?
可以使用 Laravel 日志:
use Illuminate\Support\Facades\Log;
Log::info('订单检查命令已执行');
日志内容不要包含密码、完整令牌或其他敏感信息。

