<?php
namespace Illuminate\Support\Facades;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
class Gate extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return GateContract::class;
}
}
一般的,
Facade
类都继承于Illuminate\Support\Facades\Facade
。比如
Illuminate\Support\Facades\Gate
这个门面:代码中我们只需要留意
getFacadeAccessor
方法是在Illuminate\Support\Facades\Gate
中定义的就好了。 我们来分析Illuminate\Support\Facades\Facade
:魔术方法 part 1
首先我们来看末尾的
__callStatic
方法: https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L206-L224还记得 Facade 类我们是怎么调用的吗?
静态调用!比如
Gate::allows()
。因为在 Facade 类中定义了
__callStatic
魔术方法,所以只要静态调用了里面没有提供的方法,都会走到魔术方法里面。 这个魔术方法内部有一个取出实例的逻辑:代码位于 https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L123-L131
前面,我们留意了
static::getFacadeAccessor()
是位于Illuminate\Support\Facades\Gate
中的,而static::getFacadeAccessor()
运行后作为参数给了static::resolveFacadeInstance()
,后者实现为 https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L145-L162而
static::$app
就是容器对象 https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L11-L16这句 https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L161 尝试从容器对象
数组取
操作,就是调用了make
https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Container/Container.php#L1208-L1211就是从容器取出对象。
总结
getFacadeRoot
的逻辑大概为static::getFacadeAccessor()
返回是否对象,如果对象则直接使用。Facade::$resolvedInstance
数组中尝试根据$name
取出对象,避免多次调用时,每次都取。Illuminate\Foundation\Application
容器取出对象。魔术方法 part 2
拿到
$instance
后,先验证$instance
是否为空。如果是就报错A facade root has not been set.
。 https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L219-L221最后,直接把方法和参数穿透到背后的
$instance
去执行。 https://github.com/xiaohuilam/laravel/blob/ca57c288f7825c42550333b613440cb4e824b3ad/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php#L223Laravel 有很多 facade 门面,背后穿透的不只一个类(譬如
DB
、View
、Session
),这是怎么回事呢? 请看 15. Laravel 神奇的 Manager 类