要求
实现多字段(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中所有的方法传参为值传递,所以在方法内部对参数赋值不会影响该参数本身。
网友评论