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() 的闭包。

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 1

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!