Facades 原理 (代码执行流程分析)
Facades原理
Laravel IOC Container总是bind(singleton)进去类,make出类的实例对象
通过Facades可以解析出类的对象,并调用类的方法,其实质也是调用了make方法解析出类的对象
- 通过这一行简单的代码,我们没有use Cache这个类,却可以使用Cache
// 注意Cache前加\ \Cache::set('czz','18',60); dd(\Cache::get('czz'));
代码执行流程解析
1 使用Cache类,实际是调用了config/app.php中 aliases数组中的Illuminate\Support\Facades\Cache;
/**
* Prepend the load method to the auto-loader stack.
*
* @return void
*/
protected function prependToLoaderStack()
{
// 把AliasLoader::load()放入自动加载函数队列中,并置于队列头部
// 调用\Cache,实际是执行了这个方法,为Illuminate\Support\Facades\Cache注册别名Cache
spl_autoload_register([$this, 'load'], true, true);
}
/**
* Load a class alias if it is registered.
*
* @param string $alias
* @return bool|null
*/
public function load($alias)
{
if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {
$this->loadFacade($alias);
return true;
}
if (isset($this->aliases[$alias])) {
// 为Illuminate\Support\Facades\Cache注册别名Cache
return class_alias($this->aliases[$alias], $alias);
}
}
'Cache' => Illuminate\Support\Facades\Cache::class,
2 进入Illuminate\Support\Facades\Cache类,发现没有set方法和get方法,调用父类的魔术方法__callStatic,从容器中解析出类的实例对象;
- 魔术方法__callStatic
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);
}
- 解析
/**
* Get the root object behind the facade.
*
* @return mixed
*/
public static function getFacadeRoot()
{
// 相当于执行的是return static::resolveFacadeInstance("cache);
return static::resolveFacadeInstance(static::getFacadeAccessor());
}
- 从容器中解析出类的对象
protected static function resolveFacadeInstance($name)
{
// $name = ‘cache’;
if (is_object($name)) {
return $name;
}
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
return static::$resolvedInstance[$name] = static::$app[$name];
}
- $app是容器对象,因为实现了ArrayAccess接口,所以,最终调用的还是容器的make方法
public function offsetGet($key)
{
// $key = "cache";
return $this->make($key);
}
3 执行对象的方法get或者set..
$instance->$method(...$args)
本作品采用《CC 协议》,转载必须注明作者和本文链接
$this->make($key); 这个在哪个文件调用的?
找到了文件 laravel\vendor\laravel\framework\src\Illuminate\Container\Container.php
laravel\vendor\laravel\framework\src\Illuminate\Cache\CacheServiceProvider.php 这个文件定义了 cache