Facade门面模式
参考: Laravel中文社区8.5文档
环境
php
# php artisan --version
bootLaravel Framework 8.83.27
# php -v
PHP 7.4.27 (cli) (built: Dec 16 2021 22:42:18) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.27, Copyright (c), by Zend Technologies
with Xdebug v2.9.2, Copyright (c) 2002-2020, by Derick Rethans
简介
Facades
为应用程序的 服务容器 中可用的类提供了 『静态代理』。Laravel
的所有Facades
都在Illuminate\Support\facades
命名空间中定义
什么是静态代理
参考官方手册:
php静态代理是一种在运行时动态绑定方法的技术。 “后期绑定”的意思是说,
static::
不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
定义路由
导入Cache Facade
对象
php
Route::get('/', function () {
return \Illuminate\Support\Facades\Cache::get('/');
});
查看源码
php
中,调用类中不存在的方法,会调用类的__callStatic
魔术方法。 查看\Illuminate\Support\Facades\Cache
类,没有找到get
方法,代码会自动调用__callStatic
魔术方法,查看该魔术方法,
php
public static function __callStatic($method, $args)
{
// 查看方法
$instance = static::getFacadeRoot();
// 如果没有设置实例,则抛出异常
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
// 这里调用实例的$method方法传入对应的参数
return $instance->$method(...$args);
}
public static function getFacadeRoot()
{
// static::绑定的实际运行的类,即是Cache类,调用getFacadeAccessor,该方法返回的是别名字符串
// cache中并没有resolveFacadeInstance方法,所以还是调用了Facade类的resolveFacadeInstance方法
return static::resolveFacadeInstance(static::getFacadeAccessor());
}
验证一下,Cache
类下新增resolveFacadeInstance
方法
php
public static function resolveFacadeInstance($name)
{
dd('resolveFacadeInstance');
}
访问首页,跟我们猜测一致
查看Facade
类的resolveFacadeInstance
方法
php
// $name值为Cache方法中返回的字符串
protected static function resolveFacadeInstance($name)
{
// 如果$name是对象,直接返回该对象
if (is_object($name)) {
return $name;
}
// 如果$name在静态属性$resolvedInstance中存在,直接返回该对象
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
// 如果容器对象存在,从容器中解析出别名为$name的对象,并将该对象放入静态属性$resolvedInstance中,下次从属性中直接返回该对象,然后返回解析出的对象
if (static::$app) {
return static::$resolvedInstance[$name] = static::$app[$name];
}
}
resolveFacadeInstance
该方法中,如果容器对象中也不存在$name
对应的类,则会抛出异常。
总结
Facades
为应用程序的 服务容器 中可用的类提供了 『静态代理』。 Laravel
的所有 Facades
都在 Illuminate\Support\facades
命名空间中定义。 Facades
使得我们可以更方便地使用框架提供的各种服务,而不需要在每个类中都进行手动绑定。 Facades
也使得我们可以更方便地在测试中使用框架提供的服务。