Facade是容器中的类的静态代理,可以调用容器中任何对象的任何方法。
Route::get(‘/cache’, function(){
return Cache::get(‘key’);
});
要使用Facade,首先需要继承‘Illuminate\Support\Facades\Facade’类并且实现一个抽象方法‘getFacadeAccessor’。
use Illuminate\Support\Facades\Facade;
class Cache extends
Facade
{
/**
*获取组件注册名称
*
* @return string
*/
protected static function getFacadeAccessor() {
return 'cache';
}
}
‘getFacadeAccessor’ 这个方法只要返回一个容器绑定类的名字即可,当然也可以直接返回一个类如:
use
Illuminate\Support\Facades\Facade;
use Cache;
class Cache extends
Facade
{
/**
*获取组件注册名称
*
* @return string
*/
protected static function getFacadeAccessor() {
return new Cache;
}
}
Facade的核心是使用了‘__callStatic’这个魔术方法,使用了这个方法之后,即可直接调用Cache中的get方法,尽管这个方法在Cache类中并不存在。
public static
function __callStatic($method, $args)
{ $instance =static::getFacadeRoot(); //解析出实例
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return$instance->$method(...$args); //调用方法
}
然后以下的在Facade中的方法可以从容器中解析出对象:
public static function getFacadeRoot(){
return static::resolveFacadeInstance(static::getFacadeAccessor());
}
protected static function getFacadeAccessor(){
throw new RuntimeException('Facade does not implement getFacadeAccessor
method.');
}
protected static function resolveFacadeInstance($name){
if (is_object($name)) {
return $name;
}
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
return static::$resolvedInstance[$name] = static::$app[$name];
}
其中的'getFacadeAccessor'这个方法必须被重写,否者就会抛出异常。然后在'resolveFacadeInstance'这个方法中会先判断是否是一个对象,如果是的话就直接返回。所以上文说的'getFacadeAccessor'这个方法直接返回一个对象也是可以的,奥秘就在这。
然后会去判断需要解析的对象是否已经解析过了,如果解析过了就直接返回,否则会从容器中去解析再返回,这样不仅仅实现了单例,而且还可以提升性能。
得到对象后,就是直接通过对象来调用方法了。