Laravel 5.7 以队列方法发送邮件(三种场景)

laravel 5.7 自带了Email verification 的功能,使得整个邮件注册激活过程更加简单。注册用户时发送激活邮件、重新发送邮件、密码重置邮件,这些功能几乎都是 Out of box的。但默认都是同步发送,太慢了,所以改为队列异步发送!当然,前提是你已经开启了redis队列并且已经理解了5.7的这些邮件发送处理流程。

1. 注册时发送邮件

  • 创建发送注册邮件的job
    php artisan make:job SendRegisterUserEmail
  • job类的代码如下:

    class SendRegisterUserEmail implements ShouldQueue
    {
        use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
        protected $user;
    
        /**
            * Create a new job instance.
            *
            * @param         $user
            */
        public function __construct($user)
        {
            $this->user = $user;
        }
    
        /**
            * Execute the job.
            *
            * @return void
            */
        public function handle()
        {
            event(new Registered($this->user));
        }
    }
  • 新增 \App\Http\Controllers\Auth\RegisterController::register来覆盖\Illuminate\Foundation\Auth\RegistersUsers::register,因为发送邮件是在这个方法中进行的。代码如下:
    /**
    * Handle a registration request for the application.
    *
    * @param Request $request
    *
    * @return \Illuminate\Http\Response
    */
    public function register(Request $request)
    {
        $this->validator($request->all())->validate();
        $user = $this->create($request->all());
        //队列job发送邮件
        dispatch(new SendRegisterUserEmail($user));
        $this->guard()->login($user);
        return $this->registered($request, $user)?: redirect($this->redirectPath());
    }

2. 重新发送邮件

  • app/Http/Controllers/Auth/VerificationController.php 中新增 resend 方法,来复写 trait VerifiesEmails 中 的方法,从而队列异步发送邮件。代码如下:
    /**
    * Resend the email verification notification.
    *
    * @param  \Illuminate\Http\Request  $request
    * @return \Illuminate\Http\Response
    */
    public function resend(Request $request)
    {
      if ($request->user()->hasVerifiedEmail()) {
          return redirect($this->redirectPath());
      }
      //队列job发送邮件
      dispatch(new SendRegisterUserEmail($request->user()));
      return back()->with('resent', true);
    }

3. 重置密码邮件

  • php artisan make:job SendResetPasswordEmail
  • 修改 SendResetPasswordEmail中的代码,如下:

    class SendResetPasswordEmail implements ShouldQueue
    {
      use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    
      protected $user;
      protected $token;
    
      /**
       * Create a new job instance.
       *
       * @param User $user
       * @param      $token
       */
      public function __construct(User $user, $token)
      {
          $this->user = $user;
          $this->token = $token;
      }
    
      /**
       * Execute the job.
       *
       * @return void
       */
      public function handle()
      {
          $this->user->notify(new ResetPassword($this->token));
      }
    }
  • 修改 \App\Models\User::sendPasswordResetNotification 这个方法,代码如下:
    /**
    * Send the password reset notification.
    *
    * @param  string $token
    *
    * @return void
    */
    public function sendPasswordResetNotification($token)
    {
      dispatch(new SendResetPasswordEmail($this, $token));
    }

4.注意:开启Redis队列发送邮件,一定要注意代码缓存问题。详见《一次对 horizon 是否缓存的误判,导致怀疑 Redis 有 BUG,最终自己解决的经历》

All Done!

本作品采用《CC 协议》,转载必须注明作者和本文链接
日拱一卒
本帖由系统于 5年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 4
游离不2

可以试试 Notification,一样支持队列

5年前 评论

你应该在handle里面发送邮件,然后把handle里面的事件移到控制器中才对

5年前 评论
Mumujin

(new AnonymousNotifiable)
                ->route('mail', $email)
                ->notify(
                    new \App\User\Notification\UserHasRegistered(
                        $event->getUser()
                    )
                );
5年前 评论

不知道为什么发不出去私信,25772111

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
93
粉丝
85
喜欢
153
收藏
121
排名:71
访问:11.4 万
私信
所有博文
社区赞助商