You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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处直接导致任务失败的问题:

  1. 构造函数属性赋值语法错误
    任务类构造函数中写的$this->$product = $product;属于PHP可变属性写法,会尝试将传入的$product对象实例转换为字符串作为属性名赋值,根本没有给类的公共属性$product正确赋值,后续访问$this->product时会取到空值,触发报错。
    修复为:

    public function __construct(Product $product)
    {
        $this->product = $product;
    }
    
  2. 代码修改后未重启队列进程
    php artisan queue:work是常驻内存进程,启动后只会加载一次代码,后续修改业务代码如果不重启进程,进程执行的还是旧版本的错误代码。修复代码后执行以下命令重启队列即可:

    php artisan queue:restart
    

优化建议

现有实现如果用户量过大会出现单任务超时、内存溢出问题,建议调整:

  • 不要在单个任务中一次性查询全量用户发信,改用User::chunk()分块查询用户,或者给每个用户单独派发发信任务,拆分单任务负载
  • 邮件类已经实现了ShouldQueue接口,发信时可以直接调用Mail::to($user)->queue()方法,把发信逻辑本身也推入队列,避免主任务阻塞
  • 生产环境建议给队列配置合理的失败重试次数、超时时间,避免异常导致任务卡死

内容的提问来源于stack exchange,提问作者Osama Mohammed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 10:57:18