4. Laravel5学习笔记:Facade的运行机制

什么是Facades

官方文档如是说:

Facades 提供一个 静态接口 给在应用程序的 服务容器 中可以取用的类。Laravel 附带许多 facades,甚至你可能已经在不知情的状况下使用过它们!Laravel 的「facades」作为在 IoC 容器里面的基础类的静态代理,提供的语法有简洁、易表达的优点,同时维持比传统的静态方法更高的可测试性和弹性。

说实话,这段话读起来真不像人类的语言,我准备来拆解一下。
首先, Facades 是一个类,是一个什么类呢?它是基础类的一个静态代理。
其次, Facades 是可以直接从IOC容器中拿到的,对应到laravel5就是说,可以直接使用,它已经存在于app这个容器中。
最后, 为什么要有 Facades 这个东东?首先优点是:它提供的语法更简洁,易表达。这个其实不是主要原因,个人觉得最主要的原因是:便于可测试性与降低耦合性(代理模式的优点)

用例子来说明

PS:本部分内容参考自网络:原文地址

我们知道$app 在laravel中是一个特殊的全局变量,它在最初启动的时候就是ioc容器的对象实例。
于是如果我们要取从ioc容器中取一个实例出来,是这样写的:

$value = $app->make('cache')->get('key');

由于$app implements PHP的 ArrayAccess interface,所以可以更简化点,写成:

$value = $app['cache']->get('key');

你甚至可以用函数的方式写成这样:

$value = app('cache')->get('key');

这个时候Facace跳出来说,我可以写成这样:

$value = Cache::get('key');

运行机制分析

  • Facades 的命名空间
    相信只要玩过laravel的人,都会见过当遇到 Facades 的时候,导入命名空间,只需要用 use XXX 即可。不用把完整的的命名空间写出来。这是为什么?
    正常的类的命名空间,应该这样写:
use Illuminate\Support\Facades\Cache;

Facades 只需要这样写:

use Cache;

为什么能够这样?我看了一些它的运行过程,解析如下:
4. Laravel5学习笔记:Facade的运行机制_第1张图片
这幅图,中的关键点是:AliasLoader中注册的自动加载方法,它使用了我们在app.php配置中的 aliases 数组,从而通过这个别名,可以找到对应的真实类存在的文件,然后完成对象的实例化。

  • 如何构建自己的 Facades
    PS:还是以 Cache 为例子

首先需要构建的就是Cache这个类本身,实现它的功能。这里对应的文件是:
Illuminate\Cache\CacheManager (备注:由于Cache有多种实现,因此通过管理者来获取想要的Cache实现方案。)

当Cache这个类,写好之后,我们要将它绑定到一个服务提供者里边去,这里的服务提供者位置是:
Illuminate\Cache\CacheServiceProvider ,绑定部分代码是:

public function register() {
    $this->app->singleton('cache', function ($app) {
        return new CacheManager($app);
    });
    ......    
}

这里需要注意的是,绑定时,为什么要使用’cache’ 这个字符串,后面会讲到。当服务提供者写好后,需要在 app.phpproviders 的数组中配置服务提供者,此处代码如下:

'providers' => [
    /* * Laravel Framework Service Providers... */
    Illuminate\Foundation\Providers\ArtisanServiceProvider::class, Illuminate\Auth\AuthServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, Illuminate\Cache\CacheServiceProvider::class, ...... ]

完成以下步骤后,就可以构建 Facades 类了,Cache 的 Facades 的位置在 Illuminate\Support\Facades\Cache

<?php

namespace Illuminate\Support\Facades;

/** * @see \Illuminate\Cache\CacheManager * @see \Illuminate\Cache\Repository */
class Cache extends Facade {
    /** * Get the registered name of the component. * * @return string */
    protected static function getFacadeAccessor() {
        return 'cache';
    }
}

所有的 Facades 类都需要继承自 Facades ,并实现 getFacadeAccessor 方法。它的工作是定义要从容器解析什么。这也就是说,如果我们绑定的时候,写的是 cache ,那么这里也需要返回 cache ,要不然解析的时候,就会找不到。大家可以试试改成其它名字。
最后一步,需要配置 app.php 中的 aliases 数组,这涉及到 Facades 的自动加载。就是最开始画的那幅图。

'aliases' => [

    'App'       => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, 'Auth' => Illuminate\Support\Facades\Auth::class, 'Blade' => Illuminate\Support\Facades\Blade::class, 'Bus' => Illuminate\Support\Facades\Bus::class, 'Cache' => Illuminate\Support\Facades\Cache::class, ...... ]

到这里, Facades 的运行解析机制,以及怎样创建自己的 Facades 都已经讲解完毕。
希望对大家有帮助,转载请注明出处!

Laravel5专题目录

你可能感兴趣的:(代理,ioc容器,静态代理,laravel5,Facades)