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文件,然后缓存再此。

2.3 - Laravel - 5.6 - Facade - Facades Real-Time 机制

我们如果打开这个文件就会看见如下代码:

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 协议》,转载必须注明作者和本文链接
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!