Facades 类别名设置流程 (class_alias)

Facade类别名设置

场景描述:

// web.php中
Route::get('/', function () {
    return view('welcome');
});
  • 为何能直接使用Route,其实是调用了Illuminate\Support\Facades\Route类。然后通过facade获取对象执行对象方法(看我上一篇文章facade原理)
  • 为何调用Route也就调用了Illuminate\Support\Facades\Route类,这就是这篇文章的核心:
  • class_alias:为一个类创建别名

核心代码 类:Illuminate\Foundation\AliasLoader

public function load($alias)
    {
        if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {
            $this->loadFacade($alias);

            return true;
        }

      // $alias来自于config/app.php中aliases数组中的一个键值队如:       
      // 'Route' => Illuminate\Support\Facades\Route::class 中的键“Route”
        if (isset($this->aliases[$alias])) {
            //'Route' => Illuminate\Support\Facades\Route::class,
            // class_alias:为一个类创建别名
            return class_alias($this->aliases[$alias], $alias);
        }
    }

具体流程如下:

  • 入口文件index.php
    // 此处才包含了设置facade类别名的操作
    $response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
    );
  • 进入Illuminate\Foundation\Http\Kernel类(Kernel.php)

    /**
     * Handle an incoming HTTP request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function handle($request)
    {
        try {
            $request->enableHttpMethodParameterOverride();
            // 进入这行
            $response = $this->sendRequestThroughRouter($request);
        } catch (Exception $e) {
            $this->reportException($e);
    
            $response = $this->renderException($request, $e);
        } catch (Throwable $e) {
            $this->reportException($e = new FatalThrowableError($e));
    
            $response = $this->renderException($request, $e);
        }
    
        $this->app['events']->dispatch(
            new Events\RequestHandled($request, $response)
        );
    
        return $response;
    }
  • 进入方法sendRequestThroughRouter

    protected function sendRequestThroughRouter($request)
    {
        // 将request对象绑定到容器$app的instances数组里面,实现单例模式
        $this->app->instance('request', $request);
    
        // 实际执行了这行 unset(static::$resolvedInstance["request"]);
        Facade::clearResolvedInstance('request');
    
        // 重点:这里的操作包含执行了Facade类的别名设置
        $this->bootstrap();
    
        return (new Pipeline($this->app))
                    ->send($request)
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                    ->then($this->dispatchToRouter());
    }
  • 进入bootstrap方法
    public function bootstrap()
    {
        if (! $this->app->hasBeenBootstrapped()) {
            // 执行容器实例$app里面的bootstrapWith,携带参数是$this->bootstrappers()
            // $this->bootstrappers()最终返回的数组是Kernel实例的属性$bootstrappers
            // protected $bootstrappers = [
            //      \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
            //      \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
            //      \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
            //      \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
            //      \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
            //      \Illuminate\Foundation\Bootstrap\BootProviders::class,
            // ];
            $this->app->bootstrapWith($this->bootstrappers());
        }
    }
  • 进入Illuminate\Foundation\Application类的bootstrapWith方法

    public function bootstrapWith(array $bootstrappers)
    {
    
        $this->hasBeenBootstrapped = true;
    
        foreach ($bootstrappers as $bootstrapper) {
            $this['events']->dispatch('bootstrapping: '.$bootstrapper, [$this]);
            // 当循环到\Illuminate\Foundation\Bootstrap\RegisterFacades::class
            // Illuminate\Foundation\Bootstrap\RegisterFacades解析出类的RegisterFacades的实例对象
            // 调用RegisterFacades的bootstrap方法
            $this->make($bootstrapper)->bootstrap($this);
    
            $this['events']->dispatch('bootstrapped: '.$bootstrapper, [$this]);
        }
    }
  • 进入Illuminate\Foundation\Bootstrap\RegisterFacades类,进入bootstrap方法

    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        Facade::clearResolvedInstances();
    
        Facade::setFacadeApplication($app);
        // 这里就是上面所说的 核心代码
        // 将config/app.php 里的aliases数组里面的Facades类设置别名
        AliasLoader::getInstance(array_merge(
            $app->make('config')->get('app.aliases', []),
            $app->make(PackageManifest::class)->aliases()
        ))->register();
    }
  • 进入Illuminate\Foundation\AliasLoader类,执行文章开头说得核心代码
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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