bus::batch() 生成 batch_id 需满足三条件:laravel ≥ 8.5、队列驱动为 database 或 redis、job 类引入 batchable trait;否则 job_batches 表不写入,$batch->id 为空且回调不触发。

直接用 Bus::batch() 就行,但三个条件缺一不可:Laravel ≥ 8.5、队列驱动必须是 database 或 redis、每个 Job 类必须引入 Batchable trait。漏掉任一个,job_batches 表不写入,$batch->id 为空,回调也不触发。
为什么 Bus::batch() 调了却没生成 batch_id?
最常见原因就三个:
-
QUEUE_CONNECTION=sync:会静默降级为同步执行,不入库、无状态、无回调 - Job 类没加
use Illuminate\Bus\Batchable;:框架无法识别该任务支持批处理,整个批次构建失败(但不报错) - 队列 worker 没运行:
job_batches表只在->dispatch()时写入初始记录,worker 不启动,状态永远卡在pending_jobs = total_jobs
如何安全地在 Job 中获取当前批次进度?
不能硬查数据库或依赖全局变量,必须用 Job 实例自带的方法:
- 在
handle()开头先判断:if (! $batch = $this->batch()) { return; },因为手动 dispatch 或重试可能脱离批次上下文 -
$batch->progress()返回整数(0–100),不是小数;$batch->finishedJobs和$batch->totalJobs是原始属性,需自行算百分比 - 别在
failed()方法里调$this->batch()—— 失败时批次对象可能已被清理,应统一用catch()回调处理
大批量任务(比如 5000+)要不要硬塞进 Bus::batch()?
不建议。虽然 Bus::batch() 语义清晰,但它会在 job_batches 表写一条记录,并为每个任务生成独立队列条目。问题出在底层支撑上:
- 若用
database驱动且未优化表结构,单次插入 5000 条 job 记录可能锁表或超时 - Redis 驱动下,若内存吃紧或连接池配置低,
push阶段就容易失败 - 更稳的方案是分块 + 异步触发:
collect($ids)->chunk(50)->each(fn ($chunk) => dispatch(new ProcessChunk($chunk))
真正容易被忽略的是 timeout 默认值:24 小时从 dispatch() 调用那一刻开始倒计时,不是从第一个 Job 执行起算。如果一批任务预计跑 30 小时,必须显式加 ->timeout(108000),否则未完成的 Job 会被框架强制标记失败并终止后续执行。











