国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

深入淺出 Laravel 的 Facade 外觀系統(tǒng)

KavenFan / 2352人閱讀

摘要:外觀模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。將使用者與子系統(tǒng)從直接耦合,轉(zhuǎn)變成由外觀類提供統(tǒng)一的接口給使用者使用,以降低客戶端與子系統(tǒng)之間的耦合度。接下來將深入分析外觀服務(wù)的加載過程。引導(dǎo)程序?qū)⒃谔幚碚?qǐng)求是完成引導(dǎo)啟動(dòng)。

本文首發(fā)于 深入淺出 Laravel 的 Facade 外觀系統(tǒng),轉(zhuǎn)載請(qǐng)注明出處。

今天我們將學(xué)習(xí) Laravel 核心架構(gòu)中的另一個(gè)主題「Facade(外觀)」。

本文將從以下幾個(gè)方面出發(fā),全面講解 Laravel 中 Facade 的運(yùn)行原理,為了便于理解后續(xù)中所有 Facade 譯作「外觀」:

簡(jiǎn)單介紹「外觀」設(shè)計(jì)模式;

Laravel「外觀」的加載原理;

Laravel「外觀」基本使用。

什么是「外觀」設(shè)計(jì)模式 外觀模式定義

為子系統(tǒng)中的一組接口提供一個(gè)統(tǒng)一的入口。外觀模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。

外觀模式是一種使用頻率非常高的結(jié)構(gòu)型設(shè)計(jì)模式,它通過引入一個(gè)外觀角色來簡(jiǎn)化客戶端與子系統(tǒng)之間的交互,
為復(fù)雜的子系統(tǒng)調(diào)用提供一個(gè)統(tǒng)一的入口,降低子系統(tǒng)與客戶端的耦合度,且客戶端調(diào)用非常方便。 - 設(shè)計(jì)模式 Java 版

核心 就是在 客戶端(使用者)子系統(tǒng)(接口或服務(wù)) 之間引入一個(gè)「外觀」角色。

將使用者與子系統(tǒng)從直接耦合,轉(zhuǎn)變成由「外觀」類提供統(tǒng)一的接口給使用者使用,以降低客戶端與子系統(tǒng)之間的耦合度。

結(jié)構(gòu)示意圖:

關(guān)于「外觀模式」可以閱讀 設(shè)計(jì)模式 Java 版 - 外觀模式

Laravel 外觀組件

Laravel 中的「外觀」組件實(shí)際上是服務(wù)容器中底層類的「靜態(tài)代理」,它將 Laravel 內(nèi)核中定義的「Contracts(在 Laravel 中又
稱為服務(wù)、契約或者通常我們所說的接口)」,以靜態(tài)可調(diào)用的方式封裝到各個(gè)「外觀」服務(wù)中供我們使用。

外觀加載原理

在講解如何使用外觀組件之前,我們依舊先去深入分析「外觀」組件是如何被 Laravel 加載到項(xiàng)目中的。這一步是
用好「外觀」組件的前提。

外觀組件配置

所有內(nèi)置的外觀組件的配置數(shù)據(jù),同 Laravel 其它服務(wù)一樣被定義在 config/app.php 文件中。讓我們來瀏覽一下 aliases 節(jié)點(diǎn)的配置數(shù)據(jù)吧:

    ...
    "aliases" => [

        "App" => IlluminateSupportFacadesApp::class,
        "Artisan" => IlluminateSupportFacadesArtisan::class,
        ...
    ],
    ...

外觀配置定義格式遵循 「別名」:「外觀類」 的數(shù)據(jù)格式。當(dāng)一個(gè) HTTP 請(qǐng)求被接收時(shí),將在處理請(qǐng)求階段將這些「外觀」組件加載到服務(wù)中。

接下來將深入分析外觀服務(wù)的加載過程。

加載外觀服務(wù)

「外觀」服務(wù)的加載工作由定義在 IlluminateFoundationHttpKernel 內(nèi)核中的 IlluminateFoundationBootstrapRegisterFacades::class 啟動(dòng)程序完成。

引導(dǎo)啟動(dòng)外觀服務(wù)

如果你已經(jīng)閱讀我的另一篇文章 深入剖析 Laravel 服務(wù)提供者實(shí)現(xiàn)原理,你應(yīng)該對(duì)引導(dǎo)程序不會(huì)太陌生。

引導(dǎo)程序?qū)⒃谔幚?HTTP 請(qǐng)求是完成引導(dǎo)啟動(dòng) bootstrap()。所以這里我們需要深入到 RegisterFacades 類的內(nèi)部去了解更多細(xì)節(jié)上的處理。

make("config")->get("app.aliases", []),
            $app->make(PackageManifest::class)->aliases()
        ))->register();
    }
}

加載外觀服務(wù)有 AliasLoader 組件完成:

首先,會(huì)從配置文件 config/app.php 中讀取所有的「外觀」服務(wù)配置 aliases

再從清單文件中讀取別名服務(wù) $app->make(PackageManifest::class)->aliases()

將兩個(gè)配置數(shù)組合并后注入到 AliasLoader 完成 注冊(cè)(register)

注冊(cè)外觀服務(wù)

最后我們來瞧瞧 AliasLoader 加載器是如何將所有的「外觀」服務(wù)加載到系統(tǒng)中的。

getAliases(), $aliases);

        static::$instance->setAliases($aliases);

        return static::$instance;
    }

    /**
     * Set the registered aliases. 設(shè)置需注冊(cè)別名數(shù)據(jù)。
     */
    public function setAliases(array $aliases)
    {
        $this->aliases = $aliases;
    }

    /**
     * Register the loader on the auto-loader stack. 將加載器注冊(cè)到自動(dòng)加載中。
     */
    public function register()
    {
        if (! $this->registered) {
            $this->prependToLoaderStack();

            $this->registered = true;
        }
    }

    /**
     * Prepend the load method to the auto-loader stack. 設(shè)置自動(dòng)加載方法。
     */
    protected function prependToLoaderStack()
    {
        // 將 AliasLoader 的 load 方法作為 __autoload 的實(shí)現(xiàn)
        spl_autoload_register([$this, "load"], true, true);
    }

    /**
     * Load a class alias if it is registered.從注冊(cè)過的服務(wù)中加載這個(gè)「外觀」服務(wù)。
     */
    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);
        }
    }
}

注意 這里是知識(shí)點(diǎn),在 AliasLoader->register() 完成「外服服務(wù)注冊(cè)」涉及 PHP 兩個(gè)知識(shí)的應(yīng)用:

PHP 內(nèi)置魔術(shù)方法 __autoload 的使用;

PHP 如何給類創(chuàng)建別名。

? 1. 外觀服務(wù)的動(dòng)態(tài)引入

我們知道 __autoload 魔術(shù)方法的作用是嘗試加載未經(jīng)定義的類,這樣當(dāng)我們使用一個(gè)未經(jīng)引入的類時(shí),則會(huì)自動(dòng)的給我們引入這個(gè)類。

更優(yōu)的解決方案是通過 spl_autoload_register 函數(shù),將自定義的類加載程序作為 __autoload 的實(shí)現(xiàn),以替代默認(rèn) __autoload() 模式函數(shù)或方法的行為。

所有 prependToLoaderStack() 方法:

    /**
     * Prepend the load method to the auto-loader stack. 設(shè)置自動(dòng)加載方法。
     */
    protected function prependToLoaderStack()
    {
        // 將 AliasLoader 的 load 方法作為 __autoload 的實(shí)現(xiàn)
        spl_autoload_register([$this, "load"], true, true);
    }

就是去完成這樣的作用,將 AliasLoader->load() 方法作為自動(dòng)加載程序的實(shí)現(xiàn),在使用「外觀」服務(wù)時(shí)動(dòng)態(tài)引入這個(gè)類。

? 2. 支持外觀服務(wù)別名

我們已經(jīng)了解到當(dāng)「外觀」服務(wù)被使用時(shí),由 AliasLoader->load() 去自動(dòng)加載這個(gè)類。

與此同時(shí),load 方法通過 class_alias($original, $alias) 函數(shù)完成別名注冊(cè)。

這樣,當(dāng)我們使用 App 類時(shí)實(shí)際上就是在使用 IlluminateSupportFacadesApp 類。

很完美么,我們的「狗蛋」終于與「世界上最好的語言」畫上了等號(hào)。你就是我,我就是你。

到這里其實(shí)已經(jīng)完成了「外觀」服務(wù)工作原理分析工作的 70%

探秘 Facade

最后我們將揭開 Facade 的神秘面紗,研究一下 Laravel 是如何實(shí)現(xiàn) Facade 設(shè)計(jì)模式的。

我們拿 IlluminateSupportFacadesApp 外觀服務(wù)開刀,去解開類似 App::make() 靜態(tài)方法使用的奧秘。

深入 FacadesApp


我們看到它的實(shí)現(xiàn)內(nèi)部僅僅定義了一個(gè) getFacadeAccessor 方法,該方法的功能是獲取已注冊(cè)組件的名稱 app;除此之外,一無所有。

看來在這里我們得不到什么有用的信息了。繼續(xù)調(diào)查基類 IlluminateSupportFacadesFacade。如果你有去通便瀏覽全部的源碼。

$method(...$args);
    }
}

你會(huì)發(fā)現(xiàn)這個(gè) Facade 基類并沒有定義類似 make 的方法,那么這里能夠靜態(tài)調(diào)用 App::make() 看來是需要從 __callStatic 著手才行。

不過在這里我們需要再次厘清一個(gè)事實(shí):「外觀」模式的功能是什么?

將使用者與子系統(tǒng)從直接耦合,轉(zhuǎn)變成由「外觀」類提供統(tǒng)一的接口給使用者使用,以降低客戶端與子系統(tǒng)之間的耦合度。

這句話的意思就是我「外觀」啥也不提供,就是一層對(duì)服務(wù)(或者說組件或接口)的封裝,然后以統(tǒng)一的方式提供給你們外部調(diào)用。

好了現(xiàn)在我們來看看 Facade::__callStatic 是如何獲取實(shí)際的服務(wù)并調(diào)用響應(yīng)的方法的吧。

首先,通過 getFacadeRoot 靜態(tài)方法獲取實(shí)際服務(wù)的實(shí)例對(duì)象;

然后,調(diào)用實(shí)例對(duì)象的相關(guān)方法并返回處理結(jié)果。


getFacadeRoot 解析對(duì)象的功能中我們可以看到:它會(huì)調(diào)用實(shí)現(xiàn)「外觀」的 getFacadeAccessor 方法獲取到組件(服務(wù)或者說接口)的名稱;然后從 Laravel 服務(wù)容器 static::$app[$name](app 是在 RegisterFacades 中注冊(cè)到「外觀」中) 中解析出相關(guān)服務(wù)。

到這里,我們就將「外觀」服務(wù)的基本工作原理給分析透徹了。

另外有關(guān)「外觀」組件的一些細(xì)枝末節(jié),如:

在文檔「Facades Vs. 輔助函數(shù)」一節(jié)提到的測(cè)試驗(yàn)證是如何實(shí)現(xiàn)的 Cache::shouldReceive("get")

什么是「實(shí)時(shí) Facades」。

還是需要你自行深入到 Facade 基類去一探究竟。

掃盲 ArrayAccess 接口

另外補(bǔ)充一個(gè)知識(shí)點(diǎn)就是關(guān)于 static::$app[$name] 這一句代碼。你不經(jīng)要問,這有啥好補(bǔ)充的呢,不就是一個(gè)簡(jiǎn)單獲取數(shù)據(jù)么。

獲取數(shù)據(jù)不假,簡(jiǎn)單也不假。

不過你仔細(xì)看一下,你會(huì)發(fā)現(xiàn) static::$app 靜態(tài)成員變量難道不是一個(gè) IlluminateContractsFoundationApplication 實(shí)現(xiàn)實(shí)例么,怎么可以從對(duì)象中以數(shù)組的方式獲取值呢?

這是因?yàn)槲覀兊姆?wù)容器 IlluminateContainerContainer 實(shí)現(xiàn)了 ArrayAccess 接口。

該接口的功能是提供像訪問數(shù)組一樣訪問對(duì)象的能力的接口,這樣就可以像數(shù)組一樣訪問對(duì)象訪問成員。

/**
 *@link https://github.com/laravel/framework/blob/5.6/src/Illuminate/Container/Container.php
 */
class Container implements ArrayAccess, ContainerContract
{
    /**
     * Get the value at a given offset. 獲取一個(gè)偏移位置的值,實(shí)際上從容器中解析出服務(wù)。
     */
    public function offsetGet($key)
    {
        return $this->make($key);
    }
}
Laravel「外觀」基本使用

外觀服務(wù)的一個(gè)典型使用場(chǎng)景是在定義路由時(shí)使用 Route::get("/", ...)。這樣一看似乎「Laravel 別名服務(wù)」也就不這么神秘了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/28846.html

相關(guān)文章

  • PHP中facade pattern(外觀模式)

    摘要:本文來自原文鏈接歡迎作客我們的學(xué)習(xí)群該篇屬于底層核心技術(shù)實(shí)戰(zhàn)揭秘這一課程底層核心概念解析這一章的擴(kuò)展閱讀。考慮到學(xué)員們的基礎(chǔ)差異,為了避免視頻當(dāng)中過于詳細(xì)而連篇累牘,故將一些底層實(shí)現(xiàn)相關(guān)的知識(shí)點(diǎn)以文章形式呈現(xiàn),供大家預(yù)習(xí)和隨時(shí)查閱。 本文來自pilishen.com----原文鏈接; 歡迎作客我們的php&Laravel學(xué)習(xí)群:109256050該篇屬于《Laravel底層核心技術(shù)實(shí)戰(zhàn)...

    jaysun 評(píng)論0 收藏0
  • Laravel核心解讀 -- 外觀模式

    摘要:外觀模式的目的在于降低系統(tǒng)的復(fù)雜程度。在不引入抽象外觀類的情況下,增加新的子系統(tǒng)可能需要修改外觀類或客戶端的源代碼,違背了開閉原則。 外觀模式 外觀模式(Facade Pattern):外部與一個(gè)子系統(tǒng)的通信必須通過一個(gè)統(tǒng)一的外觀對(duì)象進(jìn)行,為子系統(tǒng)中的一組接口提供一個(gè)一致的界面,外觀模式定義了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易使用。外觀模式又稱為門面模式,它是一種對(duì)象結(jié)構(gòu)型模...

    zoomdong 評(píng)論0 收藏0
  • Laravel 創(chuàng)建自己 Facade

    摘要:使用現(xiàn)在,在任何一個(gè)控制器,或者路由的回調(diào)函數(shù)中,使用你會(huì)發(fā)現(xiàn),已經(jīng)可以好好工作了,參考文章設(shè)計(jì)模式九外觀模式結(jié)構(gòu)型服務(wù)容器實(shí)例教程深入理解控制反轉(zhuǎn)和依賴注入服務(wù)提供者實(shí)例教程創(chuàng)建測(cè)試實(shí)例 我的博客原文: http://www.qinblog.net/Articl... 前言 laravel 提供了一個(gè)靈活的模式,那就是 facade 。框架內(nèi)部的 DB、Auth、File 等功能也...

    K_B_Z 評(píng)論0 收藏0
  • 設(shè)計(jì)模式系列·Facade模式之MVC煩惱

    摘要:沒有任何意外,王小二的公司用來開發(fā)公司的主打產(chǎn)品。臃腫的著手開干吧小二打開熟悉的,找到提交訂單模塊的。要不再去請(qǐng)教下哥的煩惱小二找到哥,詳細(xì)的描述了他的問題。 流行的MVC架構(gòu)模式 如今的Web開發(fā),各種框架風(fēng)起云涌,勢(shì)如破竹。 從國民第一的ThinkPhp到稱霸全球的Laravel,這些框架有一個(gè)共同特征,都采用了MVC的架構(gòu)模式。 showImg(https://segmentfa...

    zhichangterry 評(píng)論0 收藏0
  • Laravel核心概念

    摘要:可以為服務(wù)提供者的方法設(shè)置類型提示。方法將在所有其他服務(wù)提供者均已注冊(cè)之后調(diào)用。所有服務(wù)提供者都在配置文件中注冊(cè)。可以選擇推遲服務(wù)提供者的注冊(cè),直到真正需要注冊(cè)綁定時(shí),這樣可以提供應(yīng)用程序的性能。 本文最早發(fā)布于 Rootrl的Blog 導(dǎo)言 Laravel是一款先進(jìn)的現(xiàn)代化框架,里面有一些概念非常重要。在上手Laravel之前,我認(rèn)為先弄懂這些概念是很有必要的。你甚至需要重溫下PHP...

    ddongjian0000 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<