司機帶你深入分析 Laravel 響應之檢視一

Dennis_Ritchie發表於2020-01-09

前言

過4天就要回家了,好興奮。好了不說廢話,這一篇是Laravel響應的第二篇,如果你要閱讀本篇,請先閱讀老司機帶你深入分析 Laravel 響應之一,這是十分有必要的,因為我會接著以前的程式碼講。但是這裡我要提醒大家一點,今天的這篇博文,我不會仔細的講Blade引擎,這一部分因為內容較多,所以我放在在下週單獨出來講,今天的這篇就講檢視在整個Laravel的大體流程。

司機帶你深入分析 Laravel 響應之檢視

分析

我們進入到類Illuminate\Routing\RoutertoResponse方法:

司機帶你深入分析 Laravel 響應之檢視

因為我們的檢視類Illuminate\View\View不符合上面的條件,所以程式碼會進入到我標出來的部分,所以這裡生成了一個Illuminate\Http\Response類的物件,我們這裡假設它為$response,根據老司機帶你深入分析 Laravel 響應之一講的,程式碼返回到public/index.php檔案中,所以接下來它的send方法被呼叫,Illuminate\Http\Response類本身並沒有實現send方法,但是它繼承自Symfony\Component\HttpFoundation\Response類,它的父類實現了這個方法,我們來看:

司機帶你深入分析 Laravel 響應之檢視

sendHeaders方法的作用就是傳送頭部,這個我們在老司機帶你深入分析 Laravel 響應之一講過了,今天我們關心的是這個sendContent方法,但是大家要注意了,我們的子類Illuminate\Http\Response實現了sendContent方法,我們來看:

司機帶你深入分析 Laravel 響應之檢視

因為我們的控制器返回的是一個檢視,也就是這裡的引數$contentIlluminate\View\View類實現了Illuminate\Contracts\Support\Renderable介面,所以程式碼會進入到我標出來的程式碼中,所以接下來我們進入到Illuminate\View\View類的render方法中:

司機帶你深入分析 Laravel 響應之檢視

這裡的引數$callback為null,首先呼叫renderContents在,這個是主角:

司機帶你深入分析 Laravel 響應之檢視

這個函式的程式碼中,只有getContents的呼叫對我們的分析是重要的,這個方法如下:

司機帶你深入分析 Laravel 響應之檢視

很好,分析到這裡,你是不是好奇這裡的engine屬性是何時初始化的?沒關係,老司機給你細細道來。

為了給大家講解,我寫了一個簡單的控制器DebugController,如下:

司機帶你深入分析 Laravel 響應之檢視

它的debug方法呼叫了view方法生成了一個檢視,我們來看view方法:

司機帶你深入分析 Laravel 響應之檢視

我們根據Illuminate\Contracts\View\Factory::class搜尋一下Laravel程式碼,注意搜尋的時候不要忘記名稱空間,不然你會不勞而獲的,很快,在Illuminate\Foundation\Application檔案中(實際上這部分程式碼我們已經在之前的程式碼分析過了,不記得可以回過頭去看),我們搜尋到了結果:

司機帶你深入分析 Laravel 響應之檢視

Illuminate\Contracts\View\Factory::classview相關聯,我們再搜尋view,很快,我們在Illuminate\View\ViewServiceProvider中,我們找到了答案:

司機帶你深入分析 Laravel 響應之檢視

哈哈,就是它,既然來到了這個檔案,我們有必要再看一下這個類的其它方法registerViewFinderregisterEngineResolver,這2個方法分別向容器繫結了view.finderview.engine.resolver,好了,我們registerFactory所註冊的單例方法中,首先,從全域性的容器中,獲取了view.finderview.engine.resolverview.engine.resolver就是:

司機帶你深入分析 Laravel 響應之檢視

我們看一下注冊的這個回撥方法,首先生成了一個Illuminate\View\Engines\EngineResolver類的物件,接下來的foreach迴圈,我們只關心blade值,這裡會呼叫registerBladeEngine方法:

司機帶你深入分析 Laravel 響應之檢視

上面的程式碼首先向容器中註冊了一個名為blade.compiler的單例,緊接著呼叫了Illuminate\View\Engines\EngineResolver類的register方法,這個方法也很簡單:

司機帶你深入分析 Laravel 響應之檢視

這個地方後面會用到,這裡只是先說下,好了,經過這些分析我們知道view.engine.resolver就是Illuminate\View\Engines\EngineResolver類的例項物件。

我們再來看'view.finder'

司機帶你深入分析 Laravel 響應之檢視

這個就很簡單了,Illuminate\View\FileViewFinder是一個檢視檔案尋找器,他會根據我們在config/view.php檔案中的配置尋找檢視檔案,比如我的配置:

司機帶你深入分析 Laravel 響應之檢視

關於Illuminate\View\FileViewFinder不多說,很簡單,大家有興趣的自己去看哈。

經過爬山涉水,我們得到了view.finderview.engine.resolver這2個大爺,我們回到Illuminate\View\ViewServiceProviderregisterFactory方法中,繼續看,緊接著呼叫當前類的createFactory方法:

司機帶你深入分析 Laravel 響應之檢視

這個方法也很簡潔:

司機帶你深入分析 Laravel 響應之檢視

直接返回了一個\Illuminate\View\Factory類的物件,好了,我們已經得到了想要的$factory,返回到helpers.php檔案中:

司機帶你深入分析 Laravel 響應之檢視

我們看\Illuminate\View\Factory類的make方法:

司機帶你深入分析 Laravel 響應之檢視

他這裡呼叫到了viewInstance方法,這個方法如下:

司機帶你深入分析 Laravel 響應之檢視

我們看viewInstance方法:

司機帶你深入分析 Laravel 響應之檢視

直接返回一個Illuminate\View\View類的物件,但是我們來看看getEngineFromPath方法,這個方法根據檢視檔案的副檔名確定當前所要使用的模板引擎:

司機帶你深入分析 Laravel 響應之檢視

因為我麼你的檢視檔案是blade檔案,副檔名是blade.php,所以$engine就是blade,上面我們分析過了,所以這裡的engines屬性就是Illuminate\View\Engines\EngineResolver類的物件,我們看它的resolve方法:

司機帶你深入分析 Laravel 響應之檢視

還記得,我們在上面呼叫了它的register方法:

司機帶你深入分析 Laravel 響應之檢視

所以我們呼叫register方法會得到Illuminate\View\Engines\CompilerEngine類的物件,我們再一次回到\Illuminate\View\Factory類viewInstance方法中,這裡我們在Illuminate\View\View類的建構函式中初始化了它的$engine屬性。

司機帶你深入分析 Laravel 響應之檢視

明白了這個之後,我們可以再次回到Illuminate\View\View類的getContents方法了:

司機帶你深入分析 Laravel 響應之檢視

這裡我簡要的和大家說下gatherData方法,這個方法合併我們直接傳遞給檢視的資料和我們的共享資料,共享資料是啥呢?還記不記得這個方法呼叫:

司機帶你深入分析 Laravel 響應之檢視

這個資料會在所有的模板中共享(看你的呼叫),gatherData方法的作用就是如此。

不多說,進入到Illuminate\View\Engines\CompilerEngine類的get方法:

司機帶你深入分析 Laravel 響應之檢視

它的程式碼首先就是判斷當前檢視是否過期,如果過期的話,就重新編譯檢視檔案,關於檢視檔案的編譯,我們在下週再來仔細講,這裡我們看看$compiler

司機帶你深入分析 Laravel 響應之檢視

所以他就是Illuminate\View\Compilers\BladeCompiler,關於Blade引擎,我們在下一篇部落格中講。

經過Blade引擎的編譯,我們就得到了檢視檔案的內容,我們回到Illuminate\View\View類的render方法中,檢視渲染的核心操作就算完成了,接下來的操作就和老司機帶你深入分析 Laravel 響應之一中的一模一樣了。

總結

作為Laravel檢視系列的第一篇,希望大家仔細閱讀,困難肯定是有的,但是讀懂之後的喜悅也是無以言表的,加油。鄙人有個qq群,可以交流,也可以加我的微信,下方有,qq群如下:

本作品採用《CC 協議》,轉載必須註明作者和本文連結

如果有不懂的地方,可以加我的qq:1174332406,或者是微信:itshardjs

相關文章