實現 使用者名稱或郵箱等 任意一個欄位均可登入

Kuper發表於2018-02-28

在需求中,我們經常會遇到要求使用 郵箱 / 使用者名稱 / 手機號 等 均可以登入的情況,但是 Laravel 自帶的使用者認證系統中是不能實現這個需求的,預設下,我們要麼使用郵箱,要麼使用使用者名稱,不能同時使用 :

class LoginController extends Controller
{
        public function username(){

            // return "username" ; 
            return "email" ;
        }
}

既然原生的不能實現,那麼我們就自己手動修改 LoginController 以實現我們的需求 。

  1. 首先寫登入表單(只有2個欄位 name 和 password):
    <form action="{{ url('/login') }}" method="post" >
            {{ csrf_field() }}
            <input name="name" type="text" placeholder="使用者名稱/郵箱" />
            <input name="password" type="password" placeholder="密碼" />
            <button type="submit">登入</button>
    </form>
  2. 修改 LoginController ( 為簡短,省略部分沒用的程式碼 ) :

    class LoginController extends Controller
    {
    
    use AuthenticatesUsers;
    
        // 依賴注入 Request 並儲存
    protected $request;
    public function __construct(Request $request)
    {
        $this->request = $request;
        $this->middleware('guest')->except('logout');
    }
    
        // 判斷使用者名稱是否是郵箱
    protected function nameIsEmail()
    {
        if (strpos($this->request->post('name'), '@') > 0) {
    
            return true;
        }
        return false;
    }
    
        // 覆蓋 AuthenticatesUsers validateLogin 方法
        // 在此可以完成我們要做的驗證
    protected function validateLogin(Request $request)
    {
        if ($this->nameIsEmail()) {
    
            $this->validate($request, [
                'name' => 'required|string|email:users,email',
                'password' => 'required|string',
            ]);
        }
    
        $this->validate($request, [
            'name' => 'required|string',
            'password' => 'required|string',
        ]);
    
    }
    
        // 覆蓋 AuthenticatesUsers credentials 方法
        // 注意這裡的返回值是陣列,這個陣列中的資料將用來和資料庫做欄位對比
    protected function credentials(Request $request)
    {
        if ($this->nameIsEmail()) {
    
            return array(
                'email' => $this->request->post('name'), // 注意下標為 email,對應資料表中的 email 欄位
                'password' => $this->request->post('password')
            );
        }
    
        return array(
            'name' => $this->request->post('name'), // 注意下標為 name , 對應資料表中的 name 欄位
            'password' => $this->request->post('password')
        );
    }
    }

    3、完成
    但是有的人可能會想:如果使用者名稱中剛好有 @ 字元怎麼辦?
    這個簡單,我們可以限制註冊的使用者名稱欄位只能為數字+字母+下劃線等等,禁止使用者名稱有 @ 等非法字元

小結:
第一次寫,有不對的地方望大佬指教,謝謝大家 。
透過這種方式我已經實現,但是不會上傳截圖 。還有,以上我只是實現了 使用者名稱和郵箱 的登入,手機號等登入方法和以上一樣,只需要再加些驗證和判斷就行了。

總結:就是在控制器中去覆蓋 AuthenticatesUsers trait 的 validateLogin 方法 和 credentials方法 ,如果大家對這些方法不清楚,建議好好閱讀原始碼。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章