Facades是我們在Laravel應用開發中使用頻率很高的一個組件,叫組件不太合適,其實它們是一組靜態類接口或者說代理,讓開發者能簡單的訪問綁定到服務容器里的各種服務。Laravel文檔中對Facades的解釋如下:
Facades 為html' target='_blank'>應用程序的 服務容器 中可用的類提供了一個「靜態」接口。Laravel 本身附帶許多的 facades,甚至你可能在不知情的狀況下已經在使用他們!Laravel 「facades」作為在服務容器內基類的「靜態代理」,擁有簡潔、易表達的語法優點,同時維持著比傳統靜態方法更高的可測試性和靈活性。我們經常用的Route就是一個Facade, 它是/Illuminate/Support/Facades/Route類的別名,這個Facade類代理的是注冊到服務容器里的router服務,所以通過Route類我們就能夠方便地使用router服務中提供的各種服務,而其中涉及到的服務解析完全是隱式地由Laravel完成的,這在一定程度上讓應用程序代碼變的簡潔了不少。下面我們會大概看一下Facades從被注冊進Laravel框架到被應用程序使用這中間的流程。Facades是和ServiceProvider緊密配合的所以如果你了解了中間的這些流程對開發自定義Laravel組件會很有幫助。
注冊Facades說到Facades注冊又要回到再介紹其它核心組建時提到過很多次的Bootstrap階段了,在讓請求通過中間件和路由之前有一個啟動應用程序的過程:
//Class: /Illuminate/Foundation/Http/Kernelprotected function sendRequestThroughRouter($request) $this- app- instance( request , $request); Facade::clearResolvedInstance( request $this- bootstrap(); return (new Pipeline($this- app)) - send($request) - through($this- app- shouldSkipMiddleware() ? [] : $this- middleware) - then($this- dispatchToRouter());//引導啟動Laravel應用程序public function bootstrap() if (! $this- app- hasBeenBootstrapped()) { /**依次執行$bootstrappers中每一個bootstrapper的bootstrap()函數 $bootstrappers = [ Illuminate/Foundation/Bootstrap/DetectEnvironment , Illuminate/Foundation/Bootstrap/LoadConfiguration , Illuminate/Foundation/Bootstrap/ConfigureLogging , Illuminate/Foundation/Bootstrap/HandleExceptions , Illuminate/Foundation/Bootstrap/RegisterFacades , Illuminate/Foundation/Bootstrap/RegisterProviders , Illuminate/Foundation/Bootstrap/BootProviders , ];*/ $this- app- bootstrapWith($this- bootstrappers());}
在啟動應用的過程中Illuminate/Foundation/Bootstrap/RegisterFacades這個階段會注冊應用程序里用到的Facades。
class RegisterFacades * Bootstrap the given application. * @param /Illuminate/Contracts/Foundation/Application $app * @return void public function bootstrap(Application $app) Facade::clearResolvedInstances(); Facade::setFacadeApplication($app); AliasLoader::getInstance(array_merge( $app- make( config )- get( app.aliases , []), $app- make(PackageManifest::class)- aliases() ))- register();}
在這里會通過AliasLoader類的實例將為所有Facades注冊別名,Facades和別名的對應關系存放在config/app.php文件的$aliases數組中
aliases = [ App = Illuminate/Support/Facades/App::class, Artisan = Illuminate/Support/Facades/Artisan::class, Auth = Illuminate/Support/Facades/Auth::class, ...... Route = Illuminate/Support/Facades/Route::class, ......]
看一下AliasLoader里是如何注冊這些別名的
// class: Illuminate/Foundation/AliasLoaderpublic static function getInstance(array $aliases = []) if (is_null(static::$instance)) { return static::$instance = new static($aliases); $aliases = array_merge(static::$instance- getAliases(), $aliases); static::$instance- setAliases($aliases); return static::$instance;public function register() if (! $this- registered) { $this- prependToLoaderStack(); $this- registered = true;protected function prependToLoaderStack() // 把AliasLoader::load()放入自動加載函數隊列中,并置于隊列頭部 spl_autoload_register([$this, load ], true, true);}
通過上面的代碼段可以看到AliasLoader將load方法注冊到了SPL __autoload函數隊列的頭部??匆幌耹oad方法的源碼:
public function load($alias) if (isset($this- aliases[$alias])) { return class_alias($this- aliases[$alias], $alias);}
在load方法里$aliases配置里的Facade類創建了對應的別名,比如當我們使用別名類Route時PHP會通過AliasLoader的load方法為把Illuminate/Support/Facades/Route::class類創建一個別名類Route,所以我們在程序里使用別Route其實使用的就是`Illuminate/Support/Facades/Route類。
解析Facade代理的服務把Facades注冊到框架后我們在應用程序里就能使用其中的Facade了,比如注冊路由時我們經常用Route::get( /uri , Controller@action);,那么Route是怎么代理到路由服務的呢,這就涉及到在Facade里服務的隱式解析了, 我們看一下Route類的源碼:
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。
新聞熱點
疑難解答