这篇文章主要介绍了关于Laravel 的 Facade 外观系统的分析,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下
今天我们将学习 Laravel 核心架构中的另一个主题「Facade(外观)」。
本文将从以下几个方面出发,全面讲解 Laravel 中 Facade 的运行原理,为了便于理解后续中所有 Facade 译作「外观」:
-
简单介绍「外观」设计模式;
-
Laravel「外观」的加载原理;
-
Laravel「外观」基本使用。
什么是「外观」设计模式
外观模式定义
为子系统中的一组接口提供一个统一的入口。外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
外观模式是一种使用频率非常高的结构型设计模式,它通过引入一个外观角色来简化客户端与子系统之间的交互,
为复杂的子系统调用提供一个统一的入口,降低子系统与客户端的耦合度,且客户端调用非常方便。 – 设计模式 Java 版
核心 就是在 客户端(使用者) 与 子系统(接口或服务) 之间引入一个「外观」角色。
将使用者与子系统从直接耦合,转变成由「外观」类提供统一的接口给使用者使用,以降低客户端与子系统之间的耦合度。
结构示意图:
关于「外观模式」可以阅读 设计模式 Java 版 – 外观模式
Laravel 外观组件
Laravel 中的「外观」组件实际上是服务容器中底层类的「静态代理」,它将 Laravel 内核中定义的「Contracts(在 Laravel 中又
称为服务、契约或者通常我们所说的接口)」,以静态可调用的方式封装到各个「外观」服务中供我们使用。
外观加载原理
在讲解如何使用外观组件之前,我们依旧先去深入分析「外观」组件是如何被 Laravel 加载到项目中的。这一步是
用好「外观」组件的前提。
外观组件配置
所有内置的外观组件的配置数据,同 Laravel 其它服务一样被定义在 config/app.php 文件中。让我们来浏览一下 aliases 节点的配置数据吧:
... 'aliases' => [ 'App' => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, ... ], ...
外观配置定义格式遵循 「别名」:「外观类」 的数据格式。当一个 HTTP 请求被接收时,将在处理请求阶段将这些「外观」组件加载到服务中。
接下来将深入分析外观服务的加载过程。
加载外观服务
「外观」服务的加载工作由定义在 Illuminate\Foundation\Http\Kernel 内核中的 \Illuminate\Foundation\Bootstrap\RegisterFacades::class 启动程序完成。
引导启动外观服务
如果你已经阅读我的另一篇文章 深入剖析 Laravel 服务提供者实现原理,你应该对引导程序不会太陌生。
引导程序将在处理 HTTP 请求是完成引导启动 bootstrap()。所以这里我们需要深入到 RegisterFacades 类的内部去了解更多细节上的处理。
<?phpnamespace Illuminate\Foundation\Bootstrap;use Illuminate\Foundation\AliasLoader;use Illuminate\Support\Facades\Facade;use Illuminate\Foundation\PackageManifest;use Ill<p style="color:transparent">本文来源gao!%daima.com搞$代*!码$网3</p><strong>搞代gaodaima码</strong>uminate\Contracts\Foundation\Application;/** * @link https://github.com/laravel/framework/blob/56a58e0fa3d845bb992d7c64ac9bb6d0c24b745a/src/Illuminate/Foundation/Bootstrap/RegisterFacades.php */class RegisterFacades{ /** * Bootstrap the given application. 引导启动服务 */ public function bootstrap(Application $app) { // 清除已解析的「外观」服务实例 Facade::clearResolvedInstances(); // 将 Laravel 服务容器注入到「外观」服务 Facade::setFacadeApplication($app); // 加载所有外观服务 AliasLoader::getInstance(array_merge( $app->make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); }}