Laravel 5.7 以佇列方法傳送郵件(三種場景)

hustnzj發表於2018-10-24

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 協議》,轉載必須註明作者和本文連結

相關文章