Request 获得已认证用户实现过程
在控制器中可以通过 Illuminate\Http\Request 实例来访问已认证的用户。
class ProfileController extends Controller {
public function update(Request $request) {
$request->user() ;//返回已认证的用户的实例...
}
}
Illuminate\Http\Request :
class Request extends SymfonyRequest implements Arrayable, ArrayAccess
{
....
protected $userResolver;
public function user($guard = null)
{
return call_user_func($this->getUserResolver(), $guard);
}
public function getUserResolver()
{
return $this->userResolver ?: function () {
//
};
}
}
可见 $request->user() 调用 Illuminate\Http\Request 中 $userResolver 保存的闭包。$userResolver 值从何而来?
Illuminate\Auth\AuthServiceProvider 中的 registerRequestRebindHandler() 为 request 在服务容器注册了一个 rebind 回调
class AuthServiceProvider extends ServiceProvider
{
public function register()
{
...
$this->registerRequestRebindHandler();
}
protected function registerRequestRebindHandler()
{
$this->app->rebinding('request', function ($app, $request) {
$request->setUserResolver(function ($guard = null) use ($app) {
return call_user_func($app['auth']->userResolver(), $guard);
});
});
}
}
class Container implements ArrayAccess, ContainerContract
{
public function rebinding($abstract, Closure $callback)
{
$this->reboundCallbacks[$abstract = $this->getAlias($abstract)][] = $callback;
if ($this->bound($abstract)) {
return $this->make($abstract);
}
}
}
在服务容器中当 request 已经绑定实例,对 request 重新 bind() 或者 instance() 绑定,会调用 rebound() 触发先前在服务容器中注册的 request rebind 回调,也就是在 request 中注入的 UserResolver。
class Container implements ArrayAccess, ContainerContract
{
public function instance($abstract, $instance)
{
...
$isBound = $this->bound($abstract);
...
if ($isBound) {
$this->rebound($abstract);
}
return $instance;
}
public function bound($abstract)
{
return isset($this->bindings[$abstract]) ||
isset($this->instances[$abstract]) ||
$this->isAlias($abstract);
}
protected function rebound($abstract)
{
$instance = $this->make($abstract);
foreach ($this->getReboundCallbacks($abstract) as $callback) {
call_user_func($callback, $this, $instance);
}
}
protected function getReboundCallbacks($abstract)
{
if (isset($this->reboundCallbacks[$abstract])) {
return $this->reboundCallbacks[$abstract];
}
return [];
}
}
而服务容器 request 两次 instance 都在 Illuminate\Foundation\Http\Kernel 中
class Kernel implements KernelContract
{
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
$this->bootstrap();
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
}
protected function dispatchToRouter()
{
return function ($request) {
$this->app->instance('request', $request);
return $this->router->dispatch($request);
};
}
}
当在 dispatchToRouter() 绑定 request 时最终会注入 $app['auth']->userResolver() 即一个包装了 Auth::User() 的闭包。
赞个