Laravel源码入门-启动引导过程(九)RegisterFacades

上篇:Laravel源码入门-启动引导过程(八)HandleExceptions

上文介绍了 HandleExceptions,在 《Laravel源码入门-启动引导过程(五)$kernel->handle($request)》中第四个要载入的是 RegisterFacades,也就是 Foundation\Http\Kernel::bootstrapers[] 的第四个

\Illuminate\Foundation\Bootstrap\RegisterFacades::class, 如下:

// Illuminate\Foundation\Http\Kernel.php 片段

   /**
     * The bootstrap classes for the application.
     * 引导类,起引导作用的类
     *
     * @var array
     */
    protected $bootstrappers = [
        // 载入服务器环境变量(.env 文件)
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
        // 载入配置信息(config 目录)
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
        // 配置如何处理异常
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        // 注册 Facades
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        // 注册 Providers
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        // 启动 Providers
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];

我们再直接贴出 RegisterFacades 类的代码,进行分析,非常直观,如下

<?php

namespace Illuminate\Foundation\Bootstrap;

use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\Facades\Facade;
use Illuminate\Contracts\Foundation\Application;

class RegisterFacades
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        Facade::clearResolvedInstances();

        Facade::setFacadeApplication($app);

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

代码虽然直观,但是对于Laravel的初学者,有个问题是难以理解它的一些概念,Facade就是其一。少于程序语言能够做这样的概念的重构,有点做博士论文的味道,以至于我们所说的Laravel的学习曲线长,主要就是因为学术味道过于浓重,无法上手就用。

来看看Facade,collins词典的解释是:The facade of a building, especially a large one, is its front wall or the wall that faces the street.用来说明建筑,那么建筑的facade是什么呢,是他的前墙面,所谓”前墙面“实际是临街的一面,很清楚了,通俗说建筑的外立面。

谷歌出来的Facade的图片大多是这里图片呈现的样子,可以看到,建筑的外立面是需要重点装饰的,以至于我们可以通过说某个建筑外面立的样子来明显定位他。下面具体说。我们来看看大家举例子时,对于facade的经典例程,如下:

 

Cache::get('akey');

先说这句代码的意思,表面看是我们一般理解的,Cache类的一个静态方法get(),返回的是通过get()获取键值为‘akey’的值。但是实际上,这里的Cache不是缓存类,get()也不是Cache类的静态方法,甚至不是Cache类的方法。那到底是什么呢?

我们接着外立面的概念,虚拟一个类吧,Illuminate\Foundation\Building,建筑物类,假如是 laravel 的 Illuminate的基础类中的一个类。再虚拟一个类,Illumniate\Supports\Facades\Building,这个不叫建筑物类了,我们把它叫做建筑物外立面类。它位于 Illuminiate支持中的 Facades中。如果说我们要写得更清晰的话,可以使用这样写:

Illuminate\Foundation\BuildingFoundation;

Illumniate\Supports\Facades\BuildingFacade;

当然因为有 namespace 的使用,我们就不用谢后缀的同义反复了。粗浅理解,我们本身有BuildingFoundation,再给建筑外面加个壳子,就成为BuildingFacade,当都建成以后,我们再去称呼他们时,往往会用 他的外壳,或者说外观的样子来做代词指代,比如 鸟巢和水立方,实际上他们是国家体育场(http://www.n-s.cn/)和国家游泳中心(www.water-cube.com/cn)的Facade。顺理成章了,当我们以 BuildFacade::get()使用时,实际上BuildFacade没有这个方法,而是调用的 BuildFoundation的get()方法。

这样做有什么好处呢,一般认为是便于可测试性与降低耦合性,说得直白一些,就像说鸟巢和水立方,比说国家体育场和国家游泳中心更方便,和更具有好的辨认性一样。更进一步,在复杂的应用容器中,对象如星空浩繁,数量庞大,大项目更是如此,如何那么容易就能提取出、表达出某个对象呢,靠传参数、传指针的方式,已经让我们搞得晕头转向,到不如,给他做个壳子(Facade)让他更好提取出来,所有耦合性也就降低了。实际上,真正的耦合性没有降低,或者说,根本不是降低了真正的业务逻辑上的耦合性,而是laravel找到一个简便有效的办法可以访问需要访问的功能或对象而已。

总结一句,BuildingFacade 更容易地解析(make())出需要的对象 BuildingFoundation。

=======

了解了 Facade,让我们再次回到具体 的 RegisterFacades 代码清单:

<?php

namespace Illuminate\Foundation\Bootstrap;

use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\Facades\Facade;
use Illuminate\Contracts\Foundation\Application;

class RegisterFacades
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        // 第一步:清空所有已经解析的实例,源代码就一句:
        // static::$resolvedInstance = [];见 Illuminate\Support\Facades\Facade.php

        Facade::clearResolvedInstances();

        // 第二步:设置 $app,源代码也是一句:
        // static::$app = $app;

        Facade::setFacadeApplication($app);

        // 第三步:获取应用配置信息->获取Facade类别名->获取别名下的实例->注册实例
        // 下面是源代码,我们格式化一下,便于阅读和查看:
        // AliasLoader::getInstance($app->make('config')->get('app.aliases', []))->register();
        
        // 3.1 获取配置信息库(Illuminate\Cache\Repository.php)
        $config = $app->make('config');
        dump($config);
        
        // 3.2 获取配置库中的 app.aliases 所有Facade别名
        $aliases = $config->get('app.aliases', []);
        dump($aliases);

        // 3.3 有Facade别名获取别名实例(如果没有就创建:new static())
        $instance = AliasLoader::getInstance($aliases);
        // 查看注册前的 $instance。
        dump($instance);

        // 3.4 注册实例(看源码使用了spl_autoload_register([$this, 'load'], true, true);)
        $instances->register();
        // 查看注册后的 $instance。
        dump($instance);
    }
}

dump($config)结果:

dump($aliases)结果:所有的Facades(建筑的外立面)

注册前后dump($instance)结果:

附录:Facade的官方介绍:https://laravel.com/docs/5.4/facades

反思:说到Facade之于我们来说,就是穴位之于中医。中医不像西医,不知道也不想知道身体内的具体影像、或很细微的结构的东西,他就通过经脉,通过把脉知道病情,通过按摩具体穴位实现治愈功能。除此,Facade之于我们,也更像武林高手,点穴即可!点!点!Facade::xxx()!

反思:例子拓展:Facade都位于 Illuminate\Support\Facades\

仿造:https://laravel.com/docs/5.4/facades#facade-class-reference

FacadeClassService Container Binding备注
NationalStadiumIlluminate\Foundation\NationalStadiumbirdsnesthttp://www.n-s.cn/
NationalAquaticsCenterIlluminate\Foundation\NationalAquaticsCenterwatercubehttp://www.water-cube.com/cn/

下篇:Laravel源码入门-启动引导过程(十)RegisterProviders

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值