Laravel的Bus::batch()是开箱即用的批量任务方案,但需满足三条件:Laravel≥8.5、队列驱动为database或redis、每个Job类引入Batchable trait;缺一则job_batches表不写入、无batch_id、回调不触发。
直接说结论:Laravel 的
是开箱即用的批量任务解决方案,但必须满足三个硬性条件——Laravel ≥ 8.5、队列驱动为
或
、每个 Job 类都用了
trait。漏掉任一条件,
表就不会写入,前端查不到进度,回调也不触发。
为什么 Bus::batch() 调用了却没生成 batch_id?
最常见原因是队列驱动配置错误或 Job 缺少关键 trait:
时
会静默降级为同步执行,不入库、无
,必须改用
或
Job 类没引入
trait,会导致该 Job 在批次中无法被识别为可批处理任务,整个 Batch 构建失败(但不会报错)
调用了
但队列工作进程未运行,
表只在 dispatch 时写入初始状态,不启动 worker 就永远卡在
如何安全地在 Job 中获取当前批次状态?
不能依赖全局变量或外部查询,必须通过
实例方法获取实时状态:
Job handle() 内必须先检查
,因为重试或手动 dispatch 可能脱离批次上下文
返回的是整数百分比(0–100),不是小数;
和
是原始属性,需自行计算
不要在
方法里直接调用
—— 失败时批次对象可能已被清理,应改用
回调统一处理
前端轮询 job_batches 表时要注意什么?
查表本身很简单,但字段语义和更新时机容易误读:
包含「尚未开始」和「正在执行中」的任务,不是纯待办数;真正空闲的 worker 数量需结合 Horizon 或
判断
是 JSON 字符串,不是数组,PHP 中要用
解析,直接遍历会出错
字段更新有延迟:Redis 驱动下通常
不要用
查完成批次——状态字段是
(无下划线),且
回调执行完才置为该值
最易被忽略的一点:Batch 的
默认是 24 小时,但这个超时是从
开始计时,不是从第一个 Job 执行起算。如果一批任务本身要跑 25 小时(比如超大文件分片处理),必须显式调用
,否则未完成的 Job 会被框架标记为失败并终止后续执行。
Bus::batch()databaseredisBatchablejob_batchesQUEUE_CONNECTION=syncBus::batch()batch_iddatabaseredisIlluminate\Bus\Batchable->dispatch()job_batchespending_jobs = total_jobs$this->batch()if (! $batch = $this->batch()) { return; }$batch->progress()$batch->finishedJobs$batch->totalJobsfailed()$this->batch()catchpending_jobsphp artisan queue:work --statusfailed_job_idsjson_decode($batch->failed_job_ids, true)where('status', 'finished')finishedfinallytimeout()dispatch()->timeout(90000)