Laravel使用自定义Job批量发邮件 执行queue:work失败
Laravel 批量发邮件队列任务执行失败排查
问题现象
已完成队列配置、Mailtrap邮件服务对接,自定义队列Job实现给数据库所有用户批量发邮件功能,执行php artisan queue:work启动队列进程后,任务状态始终为Failed。
现有实现代码
ProductMail 邮件类
class ProductMail extends Mailable implements ShouldQueue { use Queueable, SerializesModels; public $product; public $user; public function __construct(Product $product, User $user) { $this->product = $product; $this->user = $user; } public function build() { return $this->subject($this->product->name) ->view('email.product'); } }
已创建对应邮件视图文件
NotifyUsersForProduct 自定义队列任务类
class NotifyUsersForProduct implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public $product; public function __construct(Product $product) { $this->$product = $product; } public function handle() { $users = User::all(); $users->map(function(User $user){ Mail::to($user)->send(new ProductMail($this->product, $user)); }); } }
任务调度代码
try { $product = Product::create([ 'name' => $request->input('name'), 'price' => $request->input('price'), 'quantity' => $request->input('quantity'), 'user_id' => Auth::id(), ]); NotifyUsersForProduct::dispatch($product);
报错截图

核心错误修复
你的代码存在2处直接导致任务失败的问题:
构造函数属性赋值语法错误
任务类构造函数中写的$this->$product = $product;属于PHP可变属性写法,会尝试将传入的$product对象实例转换为字符串作为属性名赋值,根本没有给类的公共属性$product正确赋值,后续访问$this->product时会取到空值,触发报错。
修复为:public function __construct(Product $product) { $this->product = $product; }代码修改后未重启队列进程
php artisan queue:work是常驻内存进程,启动后只会加载一次代码,后续修改业务代码如果不重启进程,进程执行的还是旧版本的错误代码。修复代码后执行以下命令重启队列即可:php artisan queue:restart
优化建议
现有实现如果用户量过大会出现单任务超时、内存溢出问题,建议调整:
- 不要在单个任务中一次性查询全量用户发信,改用
User::chunk()分块查询用户,或者给每个用户单独派发发信任务,拆分单任务负载 - 邮件类已经实现了
ShouldQueue接口,发信时可以直接调用Mail::to($user)->queue()方法,把发信逻辑本身也推入队列,避免主任务阻塞 - 生产环境建议给队列配置合理的失败重试次数、超时时间,避免异常导致任务卡死
内容的提问来源于stack exchange,提问作者Osama Mohammed
相关产品推荐
相关产品推荐

