如何在User模型外部重写sendPasswordResetNotification方法?
解决方法
针对你需要将密码重置通知方法移出公共User模型的需求,这里提供两种可行方案:
方案一:用自定义Trait封装逻辑(推荐,操作简单)
如果公共项目的User模型允许添加Trait引用,这是最直接的方式:
- 创建自定义Trait
在项目中新建一个Trait文件,比如app/Traits/CustomPasswordResetNotification.php,把原来的通知逻辑移进去:
<?php namespace App\Traits; use App\Notifications\ResetPasswordNotification; trait CustomPasswordResetNotification { /** * 发送密码重置通知 * * @param string $token * @return void */ public function sendPasswordResetNotification($token) { $this->notify(new ResetPasswordNotification($token)); } }
- 在User模型中引入Trait
修改公共项目的User模型,引入自定义Trait(注意要放在CanResetPassword之后,PHP会优先使用后引入Trait的同名方法):
// User.php use Illuminate\Auth\Passwords\CanResetPassword; use App\Traits\CustomPasswordResetNotification; class User extends Authenticatable { use CanResetPassword, CustomPasswordResetNotification; // 移除原来写在User模型里的sendPasswordResetNotification方法 // ... 其他原有代码 }
这样既把逻辑移到了外部文件,又确保不会使用CanResetPassword中可能存在的同名方法(实际Laravel原生的CanResetPassword没有这个方法,这里是为了满足你排除原trait方法的需求)。
方案二:事件监听+重写PasswordBroker(无侵入修改User模型)
如果完全不能修改公共的User模型,可以通过Laravel的事件系统和自定义PasswordBroker来实现:
- 创建事件监听器
新建监听器app/Listeners/SendPasswordResetNotification.php:
<?php namespace App\Listeners; use Illuminate\Auth\Events\PasswordResetRequested; use App\Notifications\ResetPasswordNotification; class SendPasswordResetNotification { public function handle(PasswordResetRequested $event) { // 发送自定义密码重置通知 $event->user->notify(new ResetPasswordNotification($event->token)); } }
- 注册事件监听
在app/Providers/EventServiceProvider.php中添加事件与监听器的绑定:
protected $listen = [ \Illuminate\Auth\Events\PasswordResetRequested::class => [ \App\Listeners\SendPasswordResetNotification::class, ], ];
- 重写PasswordBroker
为了避免User模型中原有的sendPasswordResetNotification方法被调用,需要自定义PasswordBroker替换原生实现,新建app/Auth/Passwords/PasswordBroker.php:
<?php namespace App\Auth\Passwords; use Illuminate\Auth\Passwords\PasswordBroker as BasePasswordBroker; class PasswordBroker extends BasePasswordBroker { public function sendResetLink(array $credentials) { $user = $this->getUser($credentials); if (is_null($user)) { return static::INVALID_USER; } // 只触发事件,不调用模型的sendPasswordResetNotification方法 $this->events->dispatch(new \Illuminate\Auth\Events\PasswordResetRequested($user, $this->createToken($user))); return static::RESET_LINK_SENT; } }
- 注册自定义PasswordBroker
在app/Providers/AuthServiceProvider.php的boot方法中绑定自定义实现:
use App\Auth\Passwords\PasswordBroker; public function boot() { $this->app->bind('auth.password', function ($app) { return new PasswordBroker( $app['auth.password.broker.database'], $app['auth']->createUserProvider(), $app['url'], $app['mailer'], $app['events'], config('auth.passwords.users.email') ); }); }
内容的提问来源于stack exchange,提问作者Ayşe Taş
相关产品推荐
相关产品推荐

