laravel源码学习观摩, 选了一段分析一下,也遇到一些问题 mark一下
分析:
发送重置密码的连接 App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail
发送这种连接之前 肯定是需要检查下填写的邮箱是不是自己网站的用户的, 但是这里面只有一个方法
trait SendsPasswordResetEmails 代码如下:
$response = $this->broker()->sendResetLink($request->only('email')); 处理邮件发送
$this->broker是Password Facade 定义的 (调用自身的broker)
先说结论 Illuminate\Auth\Passwords\PasswordBroker 实例
<?php namespace Illuminate\Foundation\Auth; use Illuminate\Http\Request; use Illuminate\Support\Facades\Password; trait SendsPasswordResetEmails { /** * Display the form to request a password reset link. * * @return \Illuminate\Http\Response */ public function showLinkRequestForm() { return view(''); } /** * Send a reset link to the given user. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ public function sendResetLinkEmail(Request $request) { $this->validateEmail($request); // We will send the password reset link to this user. Once we have attempted // to send the link, we will examine the response then see the message we // need to show to the user. Finally, we'll send out a proper response. $response = $this->broker()->sendResetLink( $request->only('email') ); return $response == Password::RESET_LINK_SENT ? $this->sendResetLinkResponse($response) : $this->sendResetLinkFailedResponse($request, $response); } /** * Validate the email for the given request. * * @param \Illuminate\Http\Request $request * @return void */ protected function validateEmail(Request $request) { $this->validate($request, ['email' => 'required|email']); } /** * Get the response for a successful password reset link. * * @param string $response * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ protected function sendResetLinkResponse($response) { return back()->with('status', trans($response)); } /** * Get the response for a failed password reset link. * * @param \Illuminate\Http\Request $request * @param string $response * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse */ protected function sendResetLinkFailedResponse(Request $request, $response) { return back()->withErrors( ['email' => trans($response)] ); } /** * Get the broker to be used during password reset. * * @return \Illuminate\Contracts\Auth\PasswordBroker */ public function broker() { return Password::broker(); } }
而Password Facade 是这样定义 getFacadeAccessor ; 那么'auth.password'组件是在注册的呢
Illuminate\Auth\Passwords\PasswordResetServiceProvider
/** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'auth.password'; }
而在PasswordResetServiceProvider 可以看到 'auth.password' 是 new PasswordBrokerManager($app);
class PasswordResetServiceProvider extends ServiceProvider { /** * Indicates if loading of the provider is deferred. * * @var bool */ protected $defer = true; /** * Register the service provider. * * @return void */ public function register() { $this->registerPasswordBroker(); } /** * Register the password broker instance. * * @return void */ protected function registerPasswordBroker() { $this->app->singleton('auth.password', function ($app) { return new PasswordBrokerManager($app); }); $this->app->bind('auth.password.broker', function ($app) { return $app->make('auth.password')->broker(); }); } /** * Get the services provided by the provider. * * @return array */ public function provides() { return ['auth.password', 'auth.password.broker']; } }
Illuminate\Auth\Passwords\PasswordBrokerManager 的broker 方法 Illuminate\Auth\Passwords\PasswordBroker
实例
<?php namespace Illuminate\Auth\Passwords; use Illuminate\Support\Str; use InvalidArgumentException; use Illuminate\Contracts\Auth\PasswordBrokerFactory as FactoryContract; /** * @mixin \Illuminate\Contracts\Auth\PasswordBroker */ class PasswordBrokerManager implements FactoryContract { /** * The application instance. * * @var \Illuminate\Foundation\Application */ protected $app; /** * The array of created "drivers". * * @var array */ protected $brokers = []; /** * Create a new PasswordBroker manager instance. * * @param \Illuminate\Foundation\Application $app * @return void */ public function __construct($app) { $this->app = $app; } /** * Attempt to get the broker from the local cache. * * @param string $name * @return \Illuminate\Contracts\Auth\PasswordBroker */ public function broker($name = null) { $name = $name ?: $this->getDefaultDriver(); return isset($this->brokers[$name]) ? $this->brokers[$name] : $this->brokers[$name] = $this->resolve($name); } /** * Resolve the given broker. * * @param string $name * @return \Illuminate\Contracts\Auth\PasswordBroker * * @throws \InvalidArgumentException */ protected function resolve($name) { $config = $this->getConfig($name); if (is_null($config)) { throw new InvalidArgumentException("Password resetter [{$name}] is not defined."); } // The password broker uses a token repository to validate tokens and send user // password e-mails, as well as validating that password reset process as an // aggregate service of sorts providing a convenient interface for resets. return new PasswordBroker( $this->createTokenRepository($config), $this->app['auth']->createUserProvider($config['provider'] ?? null) ); } /** * Create a token repository instance based on the given configuration. * * @param array $config * @return \Illuminate\Auth\Passwords\TokenRepositoryInterface */ protected function createTokenRepository(array $config) { $key = $this->app['config']['app.key']; if (Str::startsWith($key, 'base64:')) { $key = base64_decode(substr($key, 7)); } $connection = $config['connection'] ?? null; return new DatabaseTokenRepository( $this->app['db']->connection($connection), $this->app['hash'], $config['table'], $key, $config['expire'] ); } /** * Get the password broker configuration. * * @param string $name * @return array */ protected function getConfig($name) { return $this->app['config']["auth.passwords.{$name}"]; } /** * Get the default password broker name. * * @return string */ public function getDefaultDriver() { return $this->app['config']['auth.defaults.passwords']; } /** * Set the default password broker name. * * @param string $name * @return void */ public function setDefaultDriver($name) { $this->app['config']['auth.defaults.passwords'] = $name; } /** * Dynamically call the default driver instance. * * @param string $method * @param array $parameters * @return mixed */ public function __call($method, $parameters) { return $this->broker()->{$method}(...$parameters); } }