雖說這次專案的架構風格是要符合 RESTful API 的標準,但實際上一個 web service 並非所有 API 都一定要符合,而這篇要講部份就是一個例子。會員登入系統幾乎是多數網站的標配,而該功能包含註冊 ( register ) 和登入 ( login ),兩者皆為 POST method,而機制大致上為:
註冊:輸入( name,email,password,confirmed password )
=> 確認 email 是否與資料庫的其中一筆有重複
=> 成功註冊後會得到 token 並存到 db ( 以便之後需要驗證 )
登入:輸入 ( email,password )
=> 確認 email 和對應的 password 是否有符合
=> 成功登入後會從該使用者的 db 撈出 token 以便驗證
而為了使其更加直覺,在定義這兩者的 API endpoint 會直接分別對應註冊或登入的英文單字:
<註> 因此 user 的 API 總共會有 6 支,並非一般常見的 5 支
在前面介紹 MVC 時有提到這個詞,那在 Laravel 中,為了避免把所有的程式邏輯通通包裝在 Router 中的 Callback function 裡面,Controller 在此扮演關鍵角色,以下是 Controller 的程式架構。
以 UsersController 為例:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UsersController extends Controller
{
// All your methods here
}
在 class 裡面可以定義自己的 controller method。
在講完大致的機制後,接下來就進入實作的部份,這次首先做註冊的部份
Step 1:建立 controller
$ php artisan make:controller UsersController
Step 2:register method
註冊使用者帳號時會遇到幾個問題,以下就來詳細解釋:
client 端輸入
首先必須驗證使用者輸入,此處自己是新增一個 Validator Class,在實際註冊帳號時,我們必須驗證使用者名稱 ( name )、使用者 email、使用者密碼 ( password ),而詳細的所有驗證項目可以參考官方文件。
/*
...
*/
// 引入 Validator class
use Illuminate\Support\Facades\Validator;
class UsersController extends Controller
{
public function register(Request $request)
{
// 驗證 client 端輸入
$rules = [
'name' => ['required', 'string', 'min:2', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:6', 'max:12', 'confirmed'],
];
$validator = Validator::make($request->all(), $rules);
// 將錯誤訊息以 JSON 格式印出
if($validator->fails()){
return response(['message' => $validator->errors()]);
}
/*
...
*/
}
}
預設值插入與進一步處理
有些資料欄位的值是由系統自動安排,以及做進一步處理
/*
...
*/
// 引入 User model
use App\User;
// 引入 Hash 及 Str class
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class UsersController extends Controller
{
public function register(Request $request)
{
/*
...
*/
// 為了合併系統自動安排的值,先將之前的 request 值存在 $data 內
$data = $request->all();
// 預設值插入
$data['password'] = Hash::make($data['password']);
$data['is_admin'] = false;
$data['api_token'] = Str::random(60);
// 將存入 $data 的值插入,新增使用者
$user = User::create($data);
// 印出使用者所有資料 ( 不包含 hidden attribute ),並且取出 api_token ( 必須特別取值 )
return response(['data' => $user, 'api_token' => $user->api_token]);
}
}
完整程式碼:
*UsersController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class UsersController extends Controller
{
public function register(Request $request)
{
// 驗證 client 端輸入
$rules = [
'name' => ['required', 'string', 'min:2', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:6', 'max:12', 'confirmed'],
];
$validator = Validator::make($request->all(), $rules);
if($validator->fails()){
return response(['message' => $validator->errors()]);
}
// 預設值插入
$data = $request->all();
// 密碼雜湊
$data['password'] = Hash::make($data['password']);
$data['is_admin'] = false;
$data['api_token'] = Str::random(60);
$user = User::create($data);
return response(['data' => $user, 'api_token' => $user->api_token]);
}
}
<p.s.> 在這之前,自己先建立一個 admin user 以便日後做測試
// 先將此改成 true,之後再改回 false
$data['is_admin'] = true;
註冊帳號的 HTTP method 為 POST,依平常情況下輸入參數應該要放在 Body 內而不是在 params ( 在 URL 就會馬上被看到 )。
錯誤情形
當有些欄位沒有符合 Validation 時:
正確結果
在 MySQL 查看詳細的資料 ( 圖小抱歉 > < ):
註冊完新的使用者之後,接下來就來實作登入。
參考資料: