當面試關問你Laravel Facade,說出這幾個關鍵詞就可以
關鍵詞
- 概念
- constructor方法
- __set方法
- property屬性傳值
- 門面(外觀)設計模式定義,facade發音[fəˈsɑːd]
- 依賴注入(不需要所有的都需要手動new N多次)
- 依賴注入容器,比如springIoc或者Laravel App(容器來自動管理依賴和實例化對象)
- php相關語法及特性
- 給類起個別名: class_alias
- 自動載入器: spl_autoload_register && __autoload
- 魔術方法:__callStatic
- 介面: ArrayAccess
- static 靜態延遲綁定
- laravel中已經實現的類
- Collection類實現/vendor/laravel/framework/src/Illuminate/Support/Collection.php
- 據說:facade來源於法語,本質可以理解為外表高大上,內部相對簡單或者複雜。翻譯成漢語叫城中的村兒。符合一些場景就是上級領導來審查,我們先把街道兩邊的建築統一打理一下,這樣領導(調用者)看到的就是一個和諧、繁榮的世界~~不過話說回來,laravel中的facade里里外外我覺得都很厲害(優雅)。
facade程式碼簡單過
- index.php中註冊HttpKernel,然後
- $app(Illuminate/Foundation/Application.php)->
bootstrapWith (arrray $bootstrappers),注意這個bootstartps裡面的數組對象是硬編碼的(定義在BilibiiLaravel/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php->bootstrappers) - 然後每個facades類中都會有個bootstrap方法,類似每個provider都會有個register方法一樣~
- 以下程式碼及注釋,來自於
/vendor/laravel/framework/src/Illuminate/Foundation/Application.php public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this['events']->dispatch('bootstrapping: ' . $bootstrapper, [$this]); /*依次從容器中拿出實例對象,然後依次調用對象的bootstrap方法。沒錯,沒個bootstraper都有一個自己的bootstrap方法。他們在 /vendor/laravel/framework/src/Illuminate/Foundation/Bootstrap中有具體體現.注意他需要一個參數這個參數就是$this, 不過你可能要問,這裡是怎麼直接make了呢?make的前提不得是bind或者instance啥的嗎?簡單介紹如下: 1. 因為我們這裡看的比如cache,router等facade,他們都是通過 xxxServiceProvider 的register方法去註冊的 2. 那麼接著來的問題是,xxxServiceProvider又是什麼時候調用的?細心的看一下當前這個類的構造方法,其中有 - registerBaseBindings - registerBaseServiceProviders - registerCoreContainerAliase 3. 然後在看一下當前這個類的register方法,有一個register方法,而調用者就是解析出來的provider了, 4. 而每個provider都會有一個register方法,然後歸根到底會有一個new方法 5. 我這裡簡單加一行if判斷,可以具體走到RegisterFacades方法*/ if ($bootstrapper == 'IlluminateFoundationBootstrapRegisterFacades') { // 這個$this就是application對象,然後你可以去追一下RegisterFacades的bootstrap方法 $this->make('IlluminateFoundationBootstrapRegisterFacades')->bootstrap($this); } $this->make($bootstrapper)->bootstrap($this); $this['events']->dispatch('bootstrapped: ' . $bootstrapper, [$this]); }- Http/Kernel.php的
handle ($request)-> sendRequestThroughRouter -> bootstrap
- RegisterFacades的bootstrap方法
- AliasLoader的
register 方法,期間合併了app.php中的配置和composer中的配置,然後調用 prependToLoaderStack - 運用了
spl_autoload_register ,調用了AliasLoader自身的load方法,然後根據namespace和定義的別名去載入並renturn