要求
實現多字段(phone、email、name)登錄。
????????文檔5.5中的方法是在LoginController中添加authenticate()方法,調用Auth::attempt()自定義用戶驗證。我嘗試過這種方法并沒有效果。鏈接如下:
d.laravel-china.org/docs/5.5/authentication#protecting-routes
解決
源碼分析
????????Auth下的登錄等控制器都是通過使用 trait 來引入必要的方法,LoginController引入了AuthenticatesUsers trait,這里包含了登錄相關的邏輯,只需要重寫該trait里相應的方法即可。
????????AuthenticatesUsers中的登錄邏輯在login方法中,該方法源碼如下:
????????我們發現attempLogin()是處理登錄的方法,源碼如下:
????????credentials()方法中又調用了該trait里的username()方法,注意,username()返回的字段為request請求中攜帶的字段同時又必須是users數據表中的字段。
方法重寫
????????LoginController中重寫attemptLogin() username()方法,如下:
? ? ? ? $this->cloudAuth()方法為我項目中必須的方法,可以忽略,直接進入if條件內即可。
????????數據庫users中定義了phone、email、name三個字段,在attemptLogin()方法中根據正則表達式判斷輸入的username的類型,并將類型存到全局變量field中,username()中返回該字段。
????????為什么不直接重寫username()方法,直接重寫該方法只能根據username()返回的字段登錄,而無法實現同時使用多個字段登錄。
? ? ? ? 為什么不能直接將$request傳給attempt()方法?因為請求中獲取的輸入username的字段是唯一的,只能是指定的name、phone、email。而我們希望實現多字段登錄,在用戶驗證時才判斷登錄的字段,并用username()返回該字段,所以$request[$this->field] = $username,給$request數組添加一個新的key/value,用于保存實際的登錄字段。
? ? ? ? 注:Laravel中所有的方法傳參為值傳遞,所以在方法內部對參數賦值不會影響該參數本身。