使用 Artisan 自带的生成器创建命令类:
php artisan make:command SendWelcomeEmail --command=email:welcome
这将在 app/Console/Commands
目录下生成 SendWelcomeEmail.php
文件。
namespace App\Console\Commands;
use Illuminate\Console\Command;
class SendWelcomeEmail extends Command
{
// 命令签名:定义参数和选项
protected $signature = 'email:welcome {user} {--queue}';
// 命令描述:显示在 php artisan list 中
protected $description = '发送欢迎邮件给新注册用户';
// 命令执行逻辑
public function handle()
{
$userId = $this->argument('user');
$shouldQueue = $this->option('queue');
// 业务逻辑...
}
}
类型 | 语法示例 | 说明 |
---|---|---|
必选参数 | {name} |
执行命令时必须提供 |
可选参数 | {name?} |
执行命令时可以省略 |
带默认值参数 | {name=default} |
未提供时使用默认值 |
布尔选项 | {--force} |
出现则为 true,否则为 false |
带值选项 | {--driver=smtp} |
必须提供值,如 --driver=log |
public function handle()
{
// 批量更新用户积分
User::where('created_at', '>', now()->subMonth())
->chunkById(100, function ($users) {
foreach ($users as $user) {
$user->points += 50;
$user->save();
}
$this->info('已处理100个用户');
});
}
public function handle()
{
DB::transaction(function () {
$order = Order::create([...]);
Product::find($order->product_id)
->decrement('stock', $order->quantity);
Log::create([
'action' => 'order_created',
'order_id' => $order->id
]);
}, 3); // 最多重试3次
}
public function handle()
{
$data = DB::table('users')
->select(
'id',
'name',
DB::raw('COUNT(orders.id) as order_count')
)
->leftJoin('orders', 'users.id', '=', 'orders.user_id')
->groupBy('users.id')
->having('order_count', '>', 10)
->get();
$this->table(['ID', '姓名', '订单数'], $data->toArray());
}
public function handle()
{
$email = $this->ask('请输入邮箱地址');
// 带默认值的询问
$role = $this->ask('请选择用户角色', 'user');
// 密码输入(隐藏显示)
$password = $this->secret('请输入密码');
// 确认操作
if ($this->confirm('确定要创建此用户吗?')) {
User::create([...]);
$this->info('用户创建成功');
}
}
public function handle()
{
// 选择列表(单选)
$action = $this->choice(
'请选择操作类型',
['create', 'update', 'delete', 'cancel'],
3 // 默认选项索引
);
// 多选列表
$features = $this->choice(
'选择要启用的功能',
['analytics', 'notifications', 'api', 'chat'],
null,
null,
true // 允许多选
);
// 自动完成输入
$users = User::pluck('name', 'id')->toArray();
$selectedId = $this->anticipate('选择用户', array_values($users));
}
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// 每天凌晨2点执行
$schedule->command('email:digest')
->dailyAt('02:00')
->withoutOverlapping()
->onQueue('commands');
// 每15分钟执行一次,仅在工作日
$schedule->call(function () {
Cache::forget('stats_dashboard');
})->everyFifteenMinutes()
->weekdays();
}
$schedule->command('backup:run')
->daily()
->environments(['production', 'staging'])
->when(function () {
return Server::isHealthy();
});
$schedule->command('report:generate')
->weekly()
->sendOutputTo(storage_path('logs/schedule.log'))
->emailOutputTo('[email protected]');
; php.ini
[xdebug]
zend_extension=xdebug.so
xdebug.mode = debug
xdebug.client_host = "127.0.0.1"
xdebug.client_port = 9003
xdebug.start_with_request = trigger
xdebug.idekey = "VSCODE"
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Artisan Command",
"type": "php",
"request": "launch",
"port": 0,// 0自动分配端口, 可根据需要修改, xdebug默认端口为9003
"runtimeArgs": [// 这里的运行时参数是传递给PHP解析器的参数,注意顺序
"-dxdebug.mode=debug",
"-dxdebug.start_with_request=yes",
"-dxdebug.client_port=${port}",// 这里的配置会修改xdebug.client_port的值
"artisan", // 这个artisan是laravel的命令(就是一个PHP文件),你可以替换为其他命令
"email:welcome", // 替换为你的命令
"--user=1"
],
"cwd": "${workspaceFolder}",
"env": { // 运行环境变量配置
"DB_HOST": "192.168.2.8",
"REDIS_HOST": "192.168.2.8",
}
}
]
}
添加以上的配置后,在vscode的调试栏里面 点击 Debug Artisan Command 即可运行laravel自定义命令的调试
public function handle()
{
$users = User::where('status', 'active')->get();
// 打印查询日志
DB::connection()->enableQueryLog();
$orders = Order::whereIn('user_id', $users->pluck('id'))->get();
$this->line(json_encode(DB::getQueryLog(), JSON_PRETTY_PRINT));
// 进度指示器
$bar = $this->output->createProgressBar(count($users));
foreach ($users as $user) {
// 处理逻辑
$bar->advance();
}
$bar->finish();
$this->newLine();
}
public function handle()
{
$file = $this->argument('file');
$csvData = Excel::toArray([], $file);
$bar = $this->output->createProgressBar(count($csvData[0]));
foreach ($csvData[0] as $row) {
User::updateOrCreate(
['email' => $row['email']],
[
'name' => $row['name'],
'role' => $row['role'] ?? 'user',
'status' => 'active'
]
);
$bar->advance();
}
$bar->finish();
$this->info('数据导入完成');
}
protected function schedule(Schedule $schedule)
{
$schedule->command('logs:clean')
->weekly()
->before(function () {
Backup::database();
})
->after(function () {
Slack::send('日志清理完成');
});
}
public function handle()
{
$this->queueable()
->onQueue('imports')
->withChain([
new ProcessImportedData($this->argument('file')),
new NotifyAdmin
]);
// 处理导入逻辑
}
大数据处理:
// 使用 chunkById 避免内存溢出
User::chunkById(500, function ($users) {
// 处理逻辑
});
异步执行:
// 将耗时操作推送到队列
$this->call('report:generate', [
'--date' => today()->toDateString()
]);
缓存结果:
$data = Cache::remember('command_result', 3600, function () {
return DB::table('analytics')->sum('clicks');
});
环境检查:
public function handle()
{
if ($this->laravel->environment('production')) {
$this->error('此命令不能在生产环境执行');
return 1;
}
// 执行命令
}
确认提示:
if (!$this->confirmToProceed('确定要删除所有过期数据吗?', 'no')) {
return;
}
日志记录:
Log::channel('commands')->info(
'执行清理命令',
['user' => auth()->user()->id]
);
Laravel 自定义命令是提升开发效率和系统自动化程度的重要工具。通过合理设计命令结构、优化数据库操作、实现交互式体验和完善调试机制,你可以构建出高效、可靠且易于维护的命令行工具。掌握这些技能后,你将能够应对各种复杂的自动化任务,让开发工作更加流畅高效。
参考资源: