注册门面

未匹配的标注

简介

这一章,我们说一下 Laravel 引导程序之门面的注册,其实质是:执行 Illuminate\Foundation\Bootstrap\RegisterFacades 类中的 bootstrap 方法。

file

bootstrap 方法

不废话,直接贴 RegisterFacades 类的 bootstrap 方法

public function bootstrap(Application $app)
{
    Facade::clearResolvedInstances();

    Facade::setFacadeApplication($app);

    AliasLoader::getInstance(array_merge(
        $app->make('config')->get('app.aliases', []),
        $app->make(PackageManifest::class)->aliases()
    ))->register();
}
  • 首先,这段代码:Facade::clearResolvedInstances();

    指,清理所有门面公共父类 Illuminate\Support\Facades\Facade 保存的实例缓存。

    其本质,我们看这段代码

    public static function clearResolvedInstances()
    {
      static::$resolvedInstance = [];
    }

    明白了吧,就是将静态属性 $resolvedInstance 赋值为空数组,即为清空实例缓存

  • 其次,这段代码:Facade::setFacadeApplication($app);,门面注册的核心呀。。。

    我记得刚刚接触 Laravel 的时候,想使用 Redis,官方文档说,用 Illuminate\Support\Facades\Redis 类。我打开 Illuminate\Support\Facades\Redis,一直追踪到其父类,最后卡在下面这个方法上

    protected static function resolveFacadeInstance($name)
    {
      if (is_object($name)) {
          return $name;
      }
    
      if (isset(static::$resolvedInstance[$name])) {
          return static::$resolvedInstance[$name];
      }
    
      return static::$resolvedInstance[$name] = static::$app[$name];
    }

    最后一行,有个 static::$app[$name],当时就是不知道 static::$app 怎么给的值,现在终于找到了。。。

    我们看一下这行代码 Facade::setFacadeApplication($app); 干了什么吧

    public static function setFacadeApplication($app)
    {
      static::$app = $app;
    }

    看到了吧,static::$app 就是在这里赋的值。

  • 最后,有个小难点,也算是核心吧,就是注册类的别名

    AliasLoader::getInstance(array_merge(
      $app->make('config')->get('app.aliases', []),
      $app->make(PackageManifest::class)->aliases()
    ))->register();

    这个就是调用 AliasLoader 类的静态方法 getInstance,以 $app->make('config')->get('app.aliases', [])$app->make(PackageManifest::class)->aliases() 合并后的数组为参数,取返回值,这个返回值是对象,再调用这个对象的 register 方法。

    关于参数,$app->make('config')->get('app.aliases', []) 是有用的,取得就是 app.php 配置文件中的 aliases 数组;$app->make(PackageManifest::class)->aliases() 返回的空数组,不用理会

    1、我们看一下 AliasLoader 类的 getInstance 方法

    public static function getInstance(array $aliases = [])
    {
      if (is_null(static::$instance)) {
          return static::$instance = new static($aliases);
      }
    
      $aliases = array_merge(static::$instance->getAliases(), $aliases);
    
      static::$instance->setAliases($aliases);
    
      return static::$instance;
    }

    再来张截图,我们看一下参数 $aliases 长什么样?

    file

    • 首先,是单例模式的经典判断,如果 static::$instancenull 则实例化自身,否则跳过

    实例化自身,要调用 构造函数的,我们看看构造函数

    private function __construct($aliases)
    {
        $this->aliases = $aliases;
    }

    简单,就是一个 $aliases 数组的赋值

    • 其次,由于第一次执行,static::$instance 一定为 null ,所以,直接 return 自身实例对象

    2、我们看一下 AliasLoader 类对象的 register 方法

    public function register()
    {
      if (! $this->registered) {
          $this->prependToLoaderStack();
    
          $this->registered = true;
      }
    }
    • 首先,判断是否注册过,由于第一次执行,所以未注册过,执行 if 里面的代码
    • 其次,我们来看一下 $this->prependToLoaderStack(); 干了什么吧
    protected function prependToLoaderStack()
    {
        spl_autoload_register([$this, 'load'], true, true);
    }

    看到没,类的自动加载方法又新增一个成员,他是 AliasLoader 类对象的 load 方法。并优先执行,所以以后自动加载类,会先执行这里的 load 方法,然后执行 Composer 注册的自动加载方法

    也就是说,以后 Laravel 容器 make 一个 Redis 会先加载 Illuminate\Support\Facades\Redis::class 类,不信,你看 app.php 配置文件 aliases 数组中键为 Redis 的值是什么吧。

    因此说,我们在使用 Illuminate\Support\Facades\Redis Redis 门面的时候可以简化 use ,如下

    <?php
    
    namespace App\Http\Controllers;
    
    use App\Http\Controllers\Controller;
    use Redis;  // 这里就是简化
    
    class UserController extends Controller
    {
        /**
         * 显示给定用户的配置文件。
         *
         * @param  int  $id
         * @return Response
         */
        public function showProfile($id)
        {
            $user = Redis::get('user:profile:'.$id);
    
            return view('user.profile', ['user' => $user]);
        }
    }

本篇如有错误、不当或者需补充的内容,请各位同僚多提宝贵意见。

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。