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