2.3 - Laravel - 5.6 - Facade - Facades Real-Time 机制
上一章中load方法中存留一个情况就是 如果出现起始为 Facades\
的别名的处理未交待,其实这个机制就是facade中的real-time facade
。
简单说就是说如果在一个类路径前面加上Facades,就可以直接把该类当做Facade使用;
举例:这里只要在类ProjectFactory namespace前面加上Facades就可以把ProjectFactory当做Facade来使用。
namespace Tests\Setup;
class ProjectFactory {
public function test1()
{
return “project factory class”;
}
}
//调用的时候前面使用Facades作为起始路径
use Facades\Tests\Setup\ProjectFactory;
class runTest{
public function test()
{
return ProjectFactory::test1();
}
}
这个机制就是通过上一篇提到的自动加载spl_autoload_register
方法实现的。
他的触发要求:
a.如果发现路径Facades\Tests\Setup\ProjectFactory
没找到这个ProjectFactory类。spl_autoload_register已经将load方法添加到自动加载的队列中,他就会触发队列中的 load
函数寻找对应的ProjectFactory。通常load函数就通过require或者include引入需要的文件,这里就是存在ProjectFactory的php文件。
下面为上一章存储load方法的prependToLoaderStack()方法。
protected function prependToLoaderStack() { spl_autoload_register([$this, 'load'], true, true); }
具体实现:
1.首先看下 load 方法:
public function load($alias)
{ //1 第一步
if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {
$this->loadFacade($alias);
return true;
}
//2 第二步
if (isset($this->aliases[$alias])) {
return class_alias($this->aliases[$alias], $alias);
}
}
1.判断facade的别名中是否存在启始位置为Facades\\
的字段, 如果有就要调用loadFacade()
去加载。
1.1 调用loadFacade函数,require引入ensureFacadeExists 返回的值。就是一个文件路径。
protected function loadFacade($alias)
{
require $this->ensureFacadeExists($alias);
}
1.1.1 require引入 ensureFacadeExists()方法返回的值。
这个方法会返回一个文件地址。
protected function ensureFacadeExists($alias)
{
if (file_exists($path = storage_path('framework/cache/facade-'.sha1($alias).'.php'))) {
return $path;
}
file_put_contents($path, $this->formatFacadeStub(
$alias, file_get_contents(__DIR__.'/stubs/facade.stub')
));
return $path;
}
a.首先判断路径“framework/cache/facade-'.sha1($alias).'.php'”
下是否存在这个php文件。这个文件是由laravel生成的facade文件,然后缓存再此。
我们如果打开这个文件就会看见如下代码:
namespace Facades\Tests\Setup;
use Illuminate\Support\Facades\Facade;
/**
* @see \Tests\Setup\ProjectFactory
*/
class ProjectFactory extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'Tests\Setup\ProjectFactory';
}
}
就是一个laravel 为我们生成的ProjectFactory类,继承了facade。
2.如果不存在缓存的文件就会使用file_put_contents
创建一个这样的缓存文件
facade.stub
是laravel准备的模板文件。模板文件中有一些通用的字段,比如说类名,需要通过formatFacadeStub()方法替换掉。
总结:简单说当程序中发现一个类路径不存在,并且被调用,如这里的ProjectFactory, laravel就会触发自动加载,会到自动加载的队列中依次寻找对应的方法,通常这些方法都会引入相应的php文件。当找到load方法时候,他会判断起始是否是Facades\
开头,如果是,就会去指定的缓存文件夹中查看有没有这样的文件,如果没有,就会生成一个存入缓存文件夹。从而实现运行时facade。(产生的文件由laravel的模板格式化产生。)
所以 第一次运行时会比较慢,因为需要创建一个文件。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: