This article mainly introduces the analysis of Laravel's Facade appearance system. It has certain reference value. Now I share it with you. Friends in need can refer to it.
Today we will learn about Laravel's core architecture. Another theme "Facade".
This article will start from the following aspects to comprehensively explain the operating principle ofFacadein Laravel. In order to facilitate the understanding of allFacadein the following translation, it is translated as "appearance":
A brief introduction to the "appearance" design pattern;
The loading principle of Laravel's "appearance";
Basic use of Laravel "appearance".
Provides a unified entry for a set of interfaces in a subsystem. The facade pattern defines a high-level interface that makes this subsystem easier to use.
The appearance pattern is a very frequently used structural design pattern. It simplifies the interaction between the client and the subsystem by introducing a appearance role,
provides a complex subsystem call The unified entrance reduces the coupling between the subsystem and the client, and the client call is very convenient. - Design Pattern Java Edition
Coreis to introduce a link betweenclient (user)andsubsystem (interface or service)"Appearance" character.
Transform the direct coupling between users and subsystems into a unified interface provided by the "appearance" class for users to reduce the coupling between the client and the subsystem.
called services, contracts or what we usually call in Laravel). "Interface"), which is encapsulated into each "appearance" service in a static and callable way for us to use.
Appearance component configuration
file like other Laravel services. Let's take a look at the configuration data of thealiasesnode:
... 'aliases' => [ 'App' => Illuminate\Support\Facades\App::class, 'Artisan' => Illuminate\Support\Facades\Artisan::class, ... ], ...
. When an HTTP request is received, these "look and feel" components are loaded into the service during the request processing phase.Next, we will conduct an in-depth analysis of the loading process of the appearance service.
Load Appearance Service
kernel\Illuminate\Foundation\Bootstrap \RegisterFacades::classLauncher completes.Boot Start Appearance Service
The bootstrap will complete the boot startup
bootstrap()after processing the HTTP request. So here we need to go deep into theRegisterFacadesclass to understand more detailed processing.
make('config')->get('app.aliases', []), $app->make(PackageManifest::class)->aliases() ))->register(); } }
component completion:
Read all "appearance" service configurationaliases;
;
Completeregistration (register).
loader loads all “appearance” services into the system.
getAliases(), $aliases); static::$instance->setAliases($aliases); return static::$instance; } /** * Set the registered aliases. 设置需注册别名数据。 */ public function setAliases(array $aliases) { $this->aliases = $aliases; } /** * Register the loader on the auto-loader stack. 将加载器注册到自动加载中。 */ public function register() { if (! $this->registered) { $this->prependToLoaderStack(); $this->registered = true; } } /** * Prepend the load method to the auto-loader stack. 设置自动加载方法。 */ protected function prependToLoaderStack() { // 将 AliasLoader 的 load 方法作为 __autoload 的实现 spl_autoload_register([$this, 'load'], true, true); } /** * Load a class alias if it is registered.从注册过的服务中加载这个「外观」服务。 */ public function load($alias) { if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) { $this->loadFacade($alias); return true; } if (isset($this->aliases[$alias])) { return class_alias($this->aliases[$alias], $alias); } } }
Here is a knowledge point. Completing "Foreign Service Registration" inAliasLoader->register()involves the application of two PHP knowledge:
;
We know that the
__autoloadmagic method is to try to load undefined classes, so that when When we use an unintroduced class, this class will be automatically introduced for us.
更优的解决方案是通过spl_autoload_register函数,将自定义的类加载程序作为__autoload的实现,以替代默认__autoload()模式函数或方法的行为。
所有prependToLoaderStack()方法:
/** * Prepend the load method to the auto-loader stack. 设置自动加载方法。 */ protected function prependToLoaderStack() { // 将 AliasLoader 的 load 方法作为 __autoload 的实现 spl_autoload_register([$this, 'load'], true, true); }
就是去完成这样的作用,将AliasLoader->load()方法作为自动加载程序的实现,在使用「外观」服务时动态引入这个类。
➤ 2. 支持外观服务别名
我们已经了解到当「外观」服务被使用时,由AliasLoader->load()去自动加载这个类。
与此同时,load 方法通过class_alias($original, $alias)函数完成别名注册。
这样,当我们使用App类时实际上就是在使用Illuminate\Support\Facades\App类。
很完美么,我们的「狗蛋」终于与「世界上最好的语言」画上了等号。你就是我,我就是你。
到这里其实已经完成了「外观」服务工作原理分析工作的70%。
最后我们将揭开Facade的神秘面纱,研究一下 Laravel 是如何实现 Facade 设计模式的。
我们拿IlluminateSupportFacadesApp外观服务开刀,去解开类似App::make()静态方法使用的奥秘。
深入FacadesApp:
我们看到它的实现内部仅仅定义了一个getFacadeAccessor方法,该方法的功能是获取已注册组件的名称app;除此之外,一无所有。
看来在这里我们得不到什么有用的信息了。继续调查基类IlluminateSupportFacadesFacade。如果你有去通便浏览全部的源码。
$method(...$args); } }
你会发现这个Facade基类并没有定义类似make的方法,那么这里能够静态调用App::make()看来是需要从__callStatic着手才行。
不过在这里我们需要再次厘清一个事实:「外观」模式的功能是什么?
将使用者与子系统从直接耦合,转变成由「外观」类提供统一的接口给使用者使用,以降低客户端与子系统之间的耦合度。
这句话的意思就是我「外观」啥也不提供,就是一层对服务(或者说组件或接口)的封装,然后以统一的方式提供给你们外部调用。
好了现在我们来看看Facade::__callStatic是如何获取实际的服务并调用响应的方法的吧。
首先,通过getFacadeRoot静态方法获取实际服务的实例对象;
然后,调用实例对象的相关方法并返回处理结果。
从getFacadeRoot解析对象的功能中我们可以看到:它会调用实现「外观」的getFacadeAccessor方法获取到组件(服务或者说接口)的名称;然后从 Laravel 服务容器static::$app[$name](app 是在 RegisterFacades 中注册到「外观」中)中解析出相关服务。
到这里,我们就将「外观」服务的基本工作原理给分析透彻了。
另外有关「外观」组件的一些细枝末节,如:
在文档「Facades Vs. 辅助函数」一节提到的测试验证是如何实现的Cache::shouldReceive('get');
什么是「实时 Facades」。
还是需要你自行深入到Facade基类去一探究竟。
另外补充一个知识点就是关于static::$app[$name]这一句代码。你不经要问,这有啥好补充的呢,不就是一个简单获取数据么。
获取数据不假,简单也不假。
不过你仔细看一下,你会发现static::$app静态成员变量难道不是一个\Illuminate\Contracts\Foundation\Application实现实例么,怎么可以从对象中以数组的方式获取值呢?
这是因为我们的服务容器Illuminate\Container\Container实现了ArrayAccess接口。
该接口的功能是提供像访问数组一样访问对象的能力的接口,这样就可以像数组一样访问对象访问成员。
/** *@link https://github.com/laravel/framework/blob/5.6/src/Illuminate/Container/Container.php */ class Container implements ArrayAccess, ContainerContract { /** * Get the value at a given offset. 获取一个偏移位置的值,实际上从容器中解析出服务。 */ public function offsetGet($key) { return $this->make($key); } }
外观服务的一个典型使用场景是在定义路由时使用Route::get('/', ...)。这样一看似乎「Laravel 别名服务」也就不这么神秘了。
The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!
Related recommendations:
Interpretation of Laravel Service Provider (ServiceProvider)
##Laravel Core Interpretation Facades
The above is the detailed content of Analysis of Laravel's Facade appearance system. For more information, please follow other related articles on the PHP Chinese website!