站長資訊網
        最全最豐富的資訊網站

        laravel為什么要用門面

        在laravel中,因為門面能夠為應用的服務容器提供一個“靜態”接口,相比于傳統的靜態方法,門面提供的“靜態”接口相當于是服務容器底層類中的一個靜態代表,能夠提供更加靈活和易于測試的語法,所以在laravel中要用到門面。

        laravel為什么要用門面

        本文操作環境:Windows10系統、Laravel6版、Dell G3電腦。

        laravel為什么用門面

        Laravel 中的門面總體上還是遵循著門面模式的基本思想的。Laravel 中的門面是為應用的服務容器提供一個【靜態】接口,相當于是服務容器底層類中的一個【靜態代表】,能夠提供更加靈活、易于測試、優雅的語法。

        對于 Laravel 中的門面來說,我們會經常使用到,比如說緩存。

        Cache::get('key');

        再比如我們之前經常用的數據庫和 Redis 。

        DB::connection('mysql2')->table('db_test')->get()->toArray();   Redis::connection('default')->client()->get('test')

        發現沒有,門面全是用的靜態方法。但是你點過去,會發現這個門面類里面什么東西都沒有呀!

        class Cache extends Facade {     protected static function getFacadeAccessor()     {         return 'cache';     } }

        在 Facade 類中,別的方法函數我們先不用看,直接拉到最底下,你會發現一個魔術方法,__callStatic() 。

        public static function __callStatic($method, $args) {     $instance = static::getFacadeRoot();       if (! $instance) {         throw new RuntimeException('A facade root has not been set.');     }       return $instance->$method(...$args); }

        __callStatic() 的意思是通過靜態調用時如果沒有定義對應的方法,就進入到 __callStatic() 方法中,比如我們調用的 Cache::get() 這個方法,實際上當前的 Cache 門面類以及它的父類 Facade 都沒有定義這個方法,那么就直接進入到了 __callStatic() 中。接著,它就通過 getFacadeRoot() 獲取我們當前門面的實例對象,然后調用實例對象中的 get() 方法。

        好了,到此為止,其實如果面試的時候有面試官問你 Laravel 中的門面模式是如何實現的時候,你就可以自信地說核心就是這個 __callStatic() 魔術方法了。那么這個具體的實例對象又是從哪里來的呢?我們繼續往下看。

        實例對象

        接下來我們看看 Facade 中的具體實例對象是怎么獲取的。這里我們又要回到服務容器中。不過還是先從門面入口來看看吧。

        在 __callStatic() 方法中,我們會看到調用了一個 static::getFacadeRoot() 方法來獲得具體的實例對象。

        public static function getFacadeRoot() {     return static::resolveFacadeInstance(static::getFacadeAccessor()); }

        這個方法的內容很簡單,就是調用了另外兩個方法,注意 getFacadeAccessor() 是我們的各個門面子類中實現的,比如例子中就是在 Cache 這個類中實現的。它只是返回一個實例的別名,還記得這個別名是在哪里定義的嗎?我們在服務容器中看到過,就是 vendor/laravel/framework/src/Illuminate/Foundation/Application.php 中 registerCoreContainerAliases() 方法里面定義的那些。

        接下來,我們主要看的就是 static::resolveFacadeInstance() 這個方法。從名字我們可以出,它的意思是 解決門面實例 ,這貨要是不返回一個實例對象那還真對起它的名字了。

        protected static function resolveFacadeInstance($name) {     if (is_object($name)) {         return $name;     }       if (isset(static::$resolvedInstance[$name])) {         return static::$resolvedInstance[$name];     }       if (static::$app) {         return static::$resolvedInstance[$name] = static::$app[$name];     } }

        第一個判斷,如果傳遞進來的是一個對象,直接返回。第二個判斷,如果當前實例數組中已經有了,就不再創建了,類似于一個 享元模式 的效果。注意,靜態的成員數組哦!什么意思呢?靜態的全局共享的,也就是說,你這個實例對象創建之后,其他地方都可以使用,完全的單例狀態。最后一個判斷,app 也就是我們的服務容器存在的話,進行服務容器的操作。

        我們先來看下這個 app 屬性是什么時候賦值的。在講服務提供者時,Kernel 中有一個 bootstrappers 屬性數組,其中有一個 RegisterFacades 提供者。很明顯,它是用于注冊門面的一個服務提供者,在這個服務提供者中,我們會看到這樣的代碼。

        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(); }

        其中的 Facade::setFacadeApplication() 就是將 服務容器 的 Application 對象注入到了門面類的靜態成員變量 app 中。注意,同樣是靜態的,全局存在的。

        然后我們繼續回到 resolveFacadeInstance() 方法中。

        protected static function resolveFacadeInstance($name) {     // …………     // …………     if (static::$app) {         return static::$resolvedInstance[$name] = static::$app[$name];     } }

        這里怎么回事,怎么就通過 static::$app[$name] 就能獲得一個實例對象了呢?別激動,別著急,想想怎么讓一個對象可以進行這樣的數組操作?我們之前學過的哦!

        就是這個 ArrayAccess 接口,它必須實現的那幾個方法可以讓對象像數組一樣去使用。

        OK,知道原理了,我們來看看是不是這樣,找到 Application 的父類 vendor/laravel/framework/src/Illuminate/Container/Container.php 。

        class Container implements ArrayAccess, ContainerContract {     // …………     // …………     public function offsetGet($key)     {         return $this->make($key);     }     // …………     // ………… }

        真像大白了吧?不再需要我繼續多解釋了吧?關于 make() 方法在之前的服務容器中已經講解過了哦。

        好了,剩下的內容交給你了,請根據 vendor/laravel/framework/src/Illuminate/Foundation/Application.php 中 registerCoreContainerAliases() 方法中的別名找到 Cache 的具體實現類,然后分析它的 get()、set()、forget() 等方法的實現,看看它們是怎么根據我們的配置文件來使用不同的緩存存儲方案的。

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 欧美精品人爱c欧美精品| 国产精品.XX视频.XXTV| 国产高清在线精品一本大道国产| 亚洲精品成人片在线观看| 亚洲精品乱码久久久久久按摩| 亚洲国产另类久久久精品黑人| 国产高清在线精品一区小说 | 亚洲欧美精品一区久久中文字幕| 久久亚洲精品无码AV红樱桃| 91精品美女在线| 国产精品v欧美精品v日韩| 97久久超碰国产精品2021| 午夜精品免费在线观看| 国产91精品黄网在线观看| 日本熟妇亚洲欧美精品区| 日韩精品人妻系列无码专区免费 | 精品亚洲国产成AV人片传媒| 国产在线拍揄自揄视精品不卡| 北岛玲日韩精品一区二区三区| 成人精品一区二区三区中文字幕 | 伊在人亚洲香蕉精品区麻豆| 欧美日韩精品在线观看| 国产精品日本一区二区不卡视频 | 精品人妻中文字幕有码在线| 久久免费精品一区二区| 2022年国产精品久久久久| 精品国产一区二区三区不卡| 久久ww精品w免费人成| 精品一区二区三区免费毛片爱| 久久精品亚洲精品国产色婷| 久久亚洲精品国产精品| 国产在线精品免费aaa片| 国产成人精品无码播放| 国产精品岛国久久久久| 日产国产精品亚洲系列| 九九久久精品国产| 国产精品igao视频网网址| 国产精品一区二区av| 97久久超碰成人精品网站| 久久亚洲国产午夜精品理论片| 午夜影视日本亚洲欧洲精品一区|