概述
Taylor Otwell 昨天發了一條推,Laravel 5.4估計很快就要來了
即將到來的Laravel5.4,讓我最激動的一個新功能應該是,實時Facades
如果你對 Laravel Facades 還不熟悉,點選這裡學習 Facades
例子
安裝laravel 5.4
使用laravel-installer
,使用--dev
引數拿到開發版
laravel new laravel54 --dev
新建一個類
我在App目錄下建立了Milkmeowo.php
namespace App;
class Milkmeowo
{
public function meow()
{
return 'cat meow';
}
}
讓 Facade 飛起來
php 版本小於7
use Facades\App\Milkmeowo;
php 版本 7 以上可以使用 Group use declarations
use Facades\ {
App\Milkmeowo
};
在任何你需要用到的地方,這裡我在路由檔案
// pre php 7
//use Facades\App\Milkmeowo;
// php 7+
use Facades\ {
App\Milkmeowo
};
Route::get('/meow', function () {
return Milkmeowo::meow();
});
就可以看到
超級方便有木有
所以在laravel5.4中任何類都可以像Facede那樣飛起來了,但注意
千萬不要使用過渡
實時Facade實現原理
本文預設你已經熟悉Facade,本文主要講
實時 Facade
的實現原理,有關Facade的具體載入原理,不在本文討論範圍之內
相信大部分人都知道Facade是透過class_alias
來是實現的,透過Illuminate/Foundation/AliasLoader.php
進行載入
實時Facade 就是改進了load方法
/**
* The namespace for all real-time facades.
*
* @var string
*/
protected static $facadeNamespace = 'Facades\\';
/**
* 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])) {
return class_alias($this->aliases[$alias], $alias);
}
}
可以看到
if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {
$this->loadFacade($alias);
return true;
}
實時Facade
判斷alias是否在static::$facadeNamespace
名稱空間下,如果是那麼就呼叫loadFacade
方法實時載入Facade
/**
* Load a real-time facade for the given alias.
*
* @param string $alias
* @return bool
*/
protected function loadFacade($alias)
{
tap($this->ensureFacadeExists($alias), function ($path) {
require $path;
});
}
/**
* Ensure that the given alias has an existing real-time facade class.
*
* @param string $alias
* @return string
*/
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;
}
/**
* Format the facade stub with the proper namespace and class.
*
* @param string $alias
* @param string $stub
* @return string
*/
protected function formatFacadeStub($alias, $stub)
{
$replacements = [
str_replace('/', '\\', dirname(str_replace('\\', '/', $alias))),
class_basename($alias),
substr($alias, strlen(static::$facadeNamespace)),
];
return str_replace(
['DummyNamespace', 'DummyClass', 'DummyTarget'], $replacements, $stub
);
}
在loadFacade
方法中,透過ensureFacadeExists
去查詢動態生成的Facade快取檔案,如果存在則返回路徑
例如本例中Facades\App\Milkmeowo
,sha1得到下面hash
>>> sha1('Facades\App\Milkmeowo')
=> "c84beaca684289727906d76c85df52fd1de7cdbe"
實時facade會在framework/cache
目錄中生成了facade-c84beaca684289727906d76c85df52fd1de7cdbe.php
檔案
<?php
namespace Facades\App;
use Illuminate\Support\Facades\Facade;
/**
* @see \App\Milkmeowo
*/
class Milkmeowo extends Facade
{
/**
* Get the registered name of the component.
*
* @return string
*/
protected static function getFacadeAccessor()
{
return 'App\Milkmeowo';
}
}
可以看到這個檔案是標準的Facede檔案
然後透過loadFacade
require這個檔案
tap($this->ensureFacadeExists($alias), function ($path) {
require $path;
});
以上就是實時Facade的實現過程,實際上就是一個動態去生成Facade模版的方法
總結
- 要想實時Facade,只需要在你的類的名稱空間前面加上
Facades\
就好了
use Facades\你的類的名稱空間
-
使用時會生成cache檔案
-
千萬不要覺得方便了濫用,你試想一下你維護或者debug的時候
方便了超多有木有!
本作品採用《CC 協議》,轉載必須註明作者和本文連結