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