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

HarveyNorman發表於2020-07-15

上一章中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 協議》,轉載必須註明作者和本文連結

相關文章