欧美亚洲中文,在线国自产视频,欧洲一区在线观看视频,亚洲综合中文字幕在线观看

      1. <dfn id="rfwes"></dfn>
          <object id="rfwes"></object>
        1. 站長(zhǎng)資訊網(wǎng)
          最全最豐富的資訊網(wǎng)站

          laravel為什么要用門面

          在laravel中,因?yàn)殚T面能夠?yàn)閼?yīng)用的服務(wù)容器提供一個(gè)“靜態(tài)”接口,相比于傳統(tǒng)的靜態(tài)方法,門面提供的“靜態(tài)”接口相當(dāng)于是服務(wù)容器底層類中的一個(gè)靜態(tài)代表,能夠提供更加靈活和易于測(cè)試的語(yǔ)法,所以在laravel中要用到門面。

          laravel為什么要用門面

          本文操作環(huán)境:Windows10系統(tǒng)、Laravel6版、Dell G3電腦。

          laravel為什么用門面

          Laravel 中的門面總體上還是遵循著門面模式的基本思想的。Laravel 中的門面是為應(yīng)用的服務(wù)容器提供一個(gè)【靜態(tài)】接口,相當(dāng)于是服務(wù)容器底層類中的一個(gè)【靜態(tài)代表】,能夠提供更加靈活、易于測(cè)試、優(yōu)雅的語(yǔ)法。

          對(duì)于 Laravel 中的門面來(lái)說(shuō),我們會(huì)經(jīng)常使用到,比如說(shuō)緩存。

          Cache::get('key');

          再比如我們之前經(jīng)常用的數(shù)據(jù)庫(kù)和 Redis 。

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

          發(fā)現(xiàn)沒(méi)有,門面全是用的靜態(tài)方法。但是你點(diǎn)過(guò)去,會(huì)發(fā)現(xiàn)這個(gè)門面類里面什么東西都沒(méi)有呀!

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

          在 Facade 類中,別的方法函數(shù)我們先不用看,直接拉到最底下,你會(huì)發(fā)現(xiàn)一個(gè)魔術(shù)方法,__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() 的意思是通過(guò)靜態(tài)調(diào)用時(shí)如果沒(méi)有定義對(duì)應(yīng)的方法,就進(jìn)入到 __callStatic() 方法中,比如我們調(diào)用的 Cache::get() 這個(gè)方法,實(shí)際上當(dāng)前的 Cache 門面類以及它的父類 Facade 都沒(méi)有定義這個(gè)方法,那么就直接進(jìn)入到了 __callStatic() 中。接著,它就通過(guò) getFacadeRoot() 獲取我們當(dāng)前門面的實(shí)例對(duì)象,然后調(diào)用實(shí)例對(duì)象中的 get() 方法。

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

          實(shí)例對(duì)象

          接下來(lái)我們看看 Facade 中的具體實(shí)例對(duì)象是怎么獲取的。這里我們又要回到服務(wù)容器中。不過(guò)還是先從門面入口來(lái)看看吧。

          在 __callStatic() 方法中,我們會(huì)看到調(diào)用了一個(gè) static::getFacadeRoot() 方法來(lái)獲得具體的實(shí)例對(duì)象。

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

          這個(gè)方法的內(nèi)容很簡(jiǎn)單,就是調(diào)用了另外兩個(gè)方法,注意 getFacadeAccessor() 是我們的各個(gè)門面子類中實(shí)現(xiàn)的,比如例子中就是在 Cache 這個(gè)類中實(shí)現(xiàn)的。它只是返回一個(gè)實(shí)例的別名,還記得這個(gè)別名是在哪里定義的嗎?我們?cè)诜?wù)容器中看到過(guò),就是 vendor/laravel/framework/src/Illuminate/Foundation/Application.php 中 registerCoreContainerAliases() 方法里面定義的那些。

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

          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];     } }

          第一個(gè)判斷,如果傳遞進(jìn)來(lái)的是一個(gè)對(duì)象,直接返回。第二個(gè)判斷,如果當(dāng)前實(shí)例數(shù)組中已經(jīng)有了,就不再創(chuàng)建了,類似于一個(gè) 享元模式 的效果。注意,靜態(tài)的成員數(shù)組哦!什么意思呢?靜態(tài)的全局共享的,也就是說(shuō),你這個(gè)實(shí)例對(duì)象創(chuàng)建之后,其他地方都可以使用,完全的單例狀態(tài)。最后一個(gè)判斷,app 也就是我們的服務(wù)容器存在的話,進(jìn)行服務(wù)容器的操作。

          我們先來(lái)看下這個(gè) app 屬性是什么時(shí)候賦值的。在講服務(wù)提供者時(shí),Kernel 中有一個(gè) bootstrappers 屬性數(shù)組,其中有一個(gè) RegisterFacades 提供者。很明顯,它是用于注冊(cè)門面的一個(gè)服務(wù)提供者,在這個(gè)服務(wù)提供者中,我們會(huì)看到這樣的代碼。

          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() 就是將 服務(wù)容器 的 Application 對(duì)象注入到了門面類的靜態(tài)成員變量 app 中。注意,同樣是靜態(tài)的,全局存在的。

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

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

          這里怎么回事,怎么就通過(guò) static::$app[$name] 就能獲得一個(gè)實(shí)例對(duì)象了呢?別激動(dòng),別著急,想想怎么讓一個(gè)對(duì)象可以進(jìn)行這樣的數(shù)組操作?我們之前學(xué)過(guò)的哦!

          就是這個(gè) ArrayAccess 接口,它必須實(shí)現(xiàn)的那幾個(gè)方法可以讓對(duì)象像數(shù)組一樣去使用。

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

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

          真像大白了吧?不再需要我繼續(xù)多解釋了吧?關(guān)于 make() 方法在之前的服務(wù)容器中已經(jīng)講解過(guò)了哦。

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

          贊(0)
          分享到: 更多 (0)
          網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)