laravel 10任务调度器通过artisan命令触发队列任务,需将队列任务封装为命令并在kernel.php中注册定时调度,依赖非sync队列驱动及持续运行的worker。

Laravel 10 的任务调度器(Scheduler)本身不直接“调度队列任务”,而是负责定时触发 Artisan 命令;若你想让某个队列任务在固定时间执行,正确做法是:把队列任务封装成一个 Artisan 命令,再用 schedule() 注册该命令。这是 Laravel 官方推荐且最稳定的方式。
将队列任务转为可调度的 Artisan 命令
不能直接在 schedule() 中写 dispatch(new SomeJob()) —— 这样每次 schedule:run 执行时都会新建一次任务实例,但无法保证幂等、不可重试、也不受调度器生命周期控制。
正确路径是:
- 运行
php artisan make:command DispatchWelcomeEmail - 在
handle()方法中调用DispatchWelcomeEmail::dispatch($user)(或带 delay) - 确保该命令支持参数、可配置、可测试
在 Kernel.php 中注册定时调度
打开 app/Console/Kernel.php,在 schedule() 方法中添加:
$schedule->command('dispatch:welcome-email')->dailyAt('09:00');
// 或延迟执行(需队列驱动支持 delay,如 redis/database)
$schedule->command('dispatch:weekly-report')->weekly()->sundays()->at('02:00');
注意:dailyAt()、weekly() 等方法只控制「何时触发这个命令」,不控制队列任务本身的执行时机;任务入队后,由 worker 按照队列策略(如是否 delay、重试次数)处理。
确保底层队列配置就绪
调度命令能否生效,依赖队列系统正常工作:
-
驱动必须是非 sync:.env 中设
QUEUE_CONNECTION=redis或database -
Worker 必须持续运行:靠 Supervisor 守护
queue:work,不能只靠--once或手动启动 -
延迟任务需驱动支持:Redis 和 database 原生支持
delay();sync 驱动会立刻执行,忽略 delay
进阶:结合 delay 实现“精准定时”
如果希望任务严格在某时刻执行(比如每天 10:30 发送通知),可不用 dailyAt() 调度命令,而改用「立即调度 + 延迟入队」:
- 定义一个每分钟运行的轻量命令:
$schedule->command('schedule:fire-tasks')->everyMinute(); - 该命令内部检查数据库或缓存中预设的「待触发任务表」,找到当前应执行的任务,然后
dispatch(new NotifyJob())->delay(now()) - 这样既能利用调度器的稳定性,又能实现秒级精度控制(取决于 worker 轮询频率)











