laravel傳送啟用郵件的思路和問題

ccabce530發表於2018-02-01

執行環境

  1. Mac系統
  2. Mamp整合環境+php5.6
  3. laravel版本號為5.1.46

傳送啟用郵件思路:

  1. 建立使用者啟用表,使用者填寫註冊資訊,完畢之後驗證註冊資訊,通過後,將註冊資訊儲存在使用者表中。
  2. 產生一個唯一的token使用者驗證使用者啟用資訊。
  3. 將token拼接到使用者啟用郵件的後面,並給使用者傳送郵件。
  4. 將token值和使用者ID儲存在使用者啟用表中。
  5. 使用者登入郵箱之後,點選啟用超連結,返回到註冊網站。
  6. 根據使用者傳入的引數和和啟用狀態來判斷使用者是否已經啟用成功。

具體的實現過程:

1. 建立使用者啟用表

php artisan make:model App\\Http\\Models\\Common\\UserActivation -m
複製程式碼

執行了上面的命令之後,可以看到在app/Http/Models/Common目錄下面建立了UserActivation的檔案,以及在data目錄下建立了資料遷移檔案,顯示如圖:

建立的model檔案

在model檔案中的最後有一個user方法,此方法是用來出來關聯關係的,既可以根據user_activations表中的user_id來查詢出這個使用者的資訊。

資料遷移檔案

注意在上面的遷移檔案中,我在使用者啟用表中新增一個外來鍵'user_id',接下來執行資料遷移命令:

php artisan migrate
複製程式碼

這樣使用者啟用表就已經建好了,下面處理使用者註冊資訊填寫完畢後的邏輯。

2. 處理使用者註冊資訊

在使用者填寫完註冊資訊之後,需要對使用者新增的資訊進行驗證,驗證通過之後才能寫入到資料表中。目前暫時假設都已經將使用者提交的資訊能寫入到使用者表中,那麼我們就需要修改儲存使用者資訊的方法,程式碼如下:

## App/Http/Controllers/Admin/UserController.php檔案

/**
 * 儲存使用者註冊資訊的方法
 */
public function store(UserPostRequest $request) {
    $data = $request->except('_token');
    $data['password'] = Crypt::encrypt($data['password']);
    $res = User::create($data);
    if($res) {
        $token = bcrypt( $res->email . time());
        # 傳送郵件
        Mail::send( 'admin.email.test', [ 'user' => $result, 'token' => $token ], function ( $message ) use ( $result ) {
            $subject = '愛麗社群啟用郵件';
            $message->to( $result->email )->subject( $subject );
        } );

        // 儲存啟用資訊
        $addData = [
            'token' => $token,
            'user_id' => $result->id,
        ];

        $res = UserActivation::create($addData);
        if ($res) {
            return redirect( 'admin/user' );
        } else {
            return back()->with('errors', 'userActivation表資料填充失敗!');
        }
    } else {
        return back()->with('errors', 'user表資料填充失敗!');
    }
}
複製程式碼

現在可以註冊一個使用者,並填寫郵箱,可以看到已經傳送了一個啟用郵件到註冊郵箱中,顯示如圖:

啟用郵件

當然在這裡,我使用laravel自帶的傳送郵件的API,使用時需要先配置好郵件的配置項,詳情見在 Laravel 5.1 中使用SMTP驅動實現郵件傳送(含附件和圖片)詳細教程

3. 在路由中配置驗證的路由並新增驗證的控制器和方法

現在需要在route.php檔案中新增驗證路由:

Route::get('verify/account', 'Home\VerifyController@account');
複製程式碼

在命令列中執行建立控制器的命令:

php artisan make:controller Home/VerifyController --plain
複製程式碼

在驗證啟用郵件的控制器中新增account方法:

# App/Http/Controllers/Home/VerifyController.php檔案
/**
 * 驗證啟用郵件的方法
 */
public function account()
{
    $token = request( 'verify' );
    $res = UserActivation::where('token', $token)->where('active', 0)->whereBetween('updated_at', [Carbon::now()->subDay(), Carbon::now()])->first();
    if ($res) {
        $res->update(['active'=>1]);
        return redirect('/login');
    }

    return redirect('/');
}
複製程式碼

現在註冊使用者時傳送啟用郵件和

傳送使用者啟用郵件時遇到的問題

1. 閉包函式內無法使用外部的變數

使用郵件傳送函式時,因為有閉包函式,所以無法使用到外部的變數,之前的寫法,程式碼如下所示:

Mail::send('admin.email.send', ['user'=>$result,'token'=>$token], function($message) {
    $subject = '愛麗社群啟用郵件';
    $message->to( $result->email )->subject($subject);
});
複製程式碼

PHPstorm提示的錯誤資訊

但是這樣的寫法在執行的時候出現了錯誤,如圖:

提示未定義的變數

經過搜尋之後,找到了正確的寫法:

Mail::send('admin.email.send', ['user'=>$result,'token'=>$token], function($message)  use ($result) {
    $subject = '愛麗社群啟用郵件';
    $message->to( $result->email )->subject($subject);
});
複製程式碼

現在可以看到PHPstorm中也沒有錯誤資訊,而且也能傳送郵件資訊。

PHPstorm也不提示錯誤資訊

2. 傳送郵件時需要等待的時間比較長

在註冊資訊提交完畢之後,系統會給註冊使用者的郵箱中傳送一份郵件,這2個過程是同步進行的,導致響應時間比較長,所以需要解決這個問題(可以參考佇列的方式),下篇文章中再處理這個響應時間過長的問題。

總結

  1. 閉包函式內使用外部變數時需要使用use關鍵詞引入外部變數
  2. 註冊系統提交完畢之後,伺服器響應的時間比較長,準備採用佇列的方式進行處理。

相關文章