iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 12
1

前言:

雖說這次專案的架構風格是要符合 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 會直接分別對應註冊或登入的英文單字:

  • 註冊:POST /register/
  • 登入:POST /login/

<註> 因此 user 的 API 總共會有 6 支,並非一般常見的 5 支

Controller

在前面介紹 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 ),而詳細的所有驗證項目可以參考官方文件

    • name : 必填、字串、長度為 2~255 之間
    • email : 必填、字串、格式必為 email、長度不大於 255、每個使用者 email 皆為獨特
    • password : 必填、字串、長度為 6~12 之間、必須確認密碼
    /*
    ...
    */
    // 引入 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()]);
            }
    
            /*
            ...
            */
    
        }
    }
    
  • 預設值插入與進一步處理
    有些資料欄位的值是由系統自動安排,以及做進一步處理

    • password : 將使用者輸入的密碼做進一步處理
    • is_admin : 預設為 false
    • api_token : 系統隨機生成長度為 60 的字串
    /*
    ...
    */
    // 引入 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]);

    }
}

Postman 實測

<p.s.> 在這之前,自己先建立一個 admin user 以便日後做測試

// 先將此改成 true,之後再改回 false
$data['is_admin'] = true;

註冊帳號的 HTTP method 為 POST,依平常情況下輸入參數應該要放在 Body 內而不是在 params ( 在 URL 就會馬上被看到 )。

  • 錯誤情形

    當有些欄位沒有符合 Validation 時:

    image alt

  • 正確結果

    image alt

  • 在 MySQL 查看詳細的資料 ( 圖小抱歉 > < ):

    image alt

註冊完新的使用者之後,接下來就來實作登入。

參考資料:

  1. Controller : https://laravel.com/docs/6.x/controllers
  2. Validation : https://laravel.com/docs/6.x/validation

上一篇
Day 11 : user ( api routes )
下一篇
Day 13 : user ( controller -- login )
系列文
從零開始的Laravel RESTful api30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言