关于重写 sendResetResponse() 方法的trait加载机制
Trait 与类的冲突处理
当存在同名方法时,当前类的方法会覆盖 Trait 中的方法,而 Trait 中的方法会覆盖父类的方法。
例子:
目录结构如下:
OOP
--traits
--test
helloTrait.php
myHelloWord.php
helloTrait.php
代码如下:
<?php
namespace OOP\traits\test;
trait helloTrait
{
public function hello(){
echo 'this is helloTrait';
}
}
- 当
myHelloWord
类中没有声明hello()
方法时:
代码如下:
<?php
require './vendor/autoload.php';
use OOP\traits\test\helloTrait;
class myHelloWorld
{
use helloTrait;
public function sayHello(){
// 调用hello方法。
$this->hello();
}
}
$obj = new myHelloWorld();
$obj->sayHello();
毫无疑问,输出的是this is helloTrait
,也就是说调用的是trait中的hello()
方法。
- 当
myHelloWord
类中声明了hello()
方法时:
代码如下:
<?php
require './vendor/autoload.php';
use OOP\traits\test\helloTrait;
class myHelloWorld
{
use helloTrait;
public function sayHello(){
// 调用hello方法。
$this->hello();
}
public function hello(){
echo 'this is myHelloWorld';
}
}
$obj = new myHelloWorld();
$obj->sayHello();
输出的是:this is myHelloWorld
。也就是说调用的是myHelloWorld
类中的方法。也就是说当前类的hello()
方法覆盖了trait
中的hello()方法
。
正如文章开头所言:
当类
与trait
存在同名方法时,当前类的方法会覆盖 Trait 中的方法。
回到教程中重写 sendResetResponse() 方法的问题
- 先看更新密码的路由:
Route::post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update');
- 当我们点击
重置密码
的时候会调用ResetPasswordController
的reset()
方法。我们先看一下ResetPasswordController
的码源:
发现<?php namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\ResetsPasswords; use Illuminate\Http\Request; class ResetPasswordController extends Controller { use ResetsPasswords; protected $redirectTo = '/'; public function __construct() { $this->middleware('guest'); } }
ResetPasswordController
类中没有reset()
方法,但是发现使用了ResetsPasswords
trait。根据use Illuminate\Foundation\Auth\ResetsPasswords;
和教程得知:该路由调用的是ResetsPasswords
trait中的reset()
方法。我们来看一下ResetsPasswords
trait中的reset()
方法的返回值:
根据注释我们得知public function reset(Request $request) { ... // 如果重置成功,我们会调用 sendResetResponse 方法重定向到程序主页上, // 失败的话调用 sendResetFailedResponse 返回并附带错误信息 return $response == Password::PASSWORD_RESET ? $this->sendResetResponse($request, $response) : $this->sendResetFailedResponse($request, $response); }
如果重置成功,我们会调用 sendResetResponse 方法重定向到程序主页上。
回到本节的问题:重置密码成功后没有反馈。也就是说ResetsPasswords
trait中的sendResetResponse()方法
并没有达到预期的效果。但是ResetsPasswords
trait是laravel框架
自带的,最好不要去动它。更好的解决办法是覆盖trait中的sendResetResponse()方法
。
具体的解决办法
利用Trait 与类的冲突处理。即在ResetPasswordController
类中声明sendResetResponse()方法
。
<?php
...
class ResetPasswordController extends Controller
{
...
protected function sendResetResponse(Request $request, $response)
{
session()->flash('success', '密码更新成功,您已成功登录!');
return redirect($this->redirectPath());
}
}