前言
過4天就要回家了,好興奮。好了不說廢話,這一篇是Laravel響應的第二篇,如果你要閱讀本篇,請先閱讀老司機帶你深入分析 Laravel 響應之一,這是十分有必要的,因為我會接著以前的程式碼講。但是這裡我要提醒大家一點,今天的這篇博文,我不會仔細的講Blade引擎,這一部分因為內容較多,所以我放在在下週單獨出來講,今天的這篇就講檢視在整個Laravel的大體流程。
分析
我們進入到類Illuminate\Routing\Router
的toResponse
方法:
因為我們的檢視類Illuminate\View\View
不符合上面的條件,所以程式碼會進入到我標出來的部分,所以這裡生成了一個Illuminate\Http\Response
類的物件,我們這裡假設它為$response
,根據老司機帶你深入分析 Laravel 響應之一講的,程式碼返回到public/index.php
檔案中,所以接下來它的send
方法被呼叫,Illuminate\Http\Response
類本身並沒有實現send
方法,但是它繼承自Symfony\Component\HttpFoundation\Response
類,它的父類實現了這個方法,我們來看:
sendHeaders
方法的作用就是傳送頭部,這個我們在老司機帶你深入分析 Laravel 響應之一講過了,今天我們關心的是這個sendContent
方法,但是大家要注意了,我們的子類Illuminate\Http\Response
實現了sendContent
方法,我們來看:
因為我們的控制器返回的是一個檢視,也就是這裡的引數$content
,Illuminate\View\View
類實現了Illuminate\Contracts\Support\Renderable
介面,所以程式碼會進入到我標出來的程式碼中,所以接下來我們進入到Illuminate\View\View
類的render
方法中:
這裡的引數$callback
為null,首先呼叫renderContents
在,這個是主角:
這個函式的程式碼中,只有getContents
的呼叫對我們的分析是重要的,這個方法如下:
很好,分析到這裡,你是不是好奇這裡的engine
屬性是何時初始化的?沒關係,老司機給你細細道來。
為了給大家講解,我寫了一個簡單的控制器DebugController
,如下:
它的debug
方法呼叫了view
方法生成了一個檢視,我們來看view
方法:
我們根據Illuminate\Contracts\View\Factory::class
搜尋一下Laravel程式碼,注意搜尋的時候不要忘記名稱空間,不然你會不勞而獲的,很快,在Illuminate\Foundation\Application
檔案中(實際上這部分程式碼我們已經在之前的程式碼分析過了,不記得可以回過頭去看),我們搜尋到了結果:
Illuminate\Contracts\View\Factory::class
和view
相關聯,我們再搜尋view
,很快,我們在Illuminate\View\ViewServiceProvider
中,我們找到了答案:
哈哈,就是它,既然來到了這個檔案,我們有必要再看一下這個類的其它方法registerViewFinder
和registerEngineResolver
,這2個方法分別向容器繫結了view.finder
和view.engine.resolver
,好了,我們registerFactory
所註冊的單例方法中,首先,從全域性的容器中,獲取了view.finder
和view.engine.resolver
,view.engine.resolver
就是:
我們看一下注冊的這個回撥方法,首先生成了一個Illuminate\View\Engines\EngineResolver
類的物件,接下來的foreach迴圈,我們只關心blade值,這裡會呼叫registerBladeEngine
方法:
上面的程式碼首先向容器中註冊了一個名為blade.compiler
的單例,緊接著呼叫了Illuminate\View\Engines\EngineResolver
類的register
方法,這個方法也很簡單:
這個地方後面會用到,這裡只是先說下,好了,經過這些分析我們知道view.engine.resolver
就是Illuminate\View\Engines\EngineResolver
類的例項物件。
我們再來看'view.finder'
:
這個就很簡單了,Illuminate\View\FileViewFinder
是一個檢視檔案尋找器,他會根據我們在config/view.php
檔案中的配置尋找檢視檔案,比如我的配置:
關於Illuminate\View\FileViewFinder
不多說,很簡單,大家有興趣的自己去看哈。
經過爬山涉水,我們得到了view.finder
和view.engine.resolver
這2個大爺,我們回到Illuminate\View\ViewServiceProvider
的registerFactory
方法中,繼續看,緊接著呼叫當前類的createFactory
方法:
這個方法也很簡潔:
直接返回了一個\Illuminate\View\Factory
類的物件,好了,我們已經得到了想要的$factory
,返回到helpers.php
檔案中:
我們看\Illuminate\View\Factory
類的make
方法:
他這裡呼叫到了viewInstance
方法,這個方法如下:
我們看viewInstance
方法:
直接返回一個Illuminate\View\View
類的物件,但是我們來看看getEngineFromPath
方法,這個方法根據檢視檔案的副檔名確定當前所要使用的模板引擎:
因為我麼你的檢視檔案是blade檔案,副檔名是blade.php
,所以$engine
就是blade
,上面我們分析過了,所以這裡的engines
屬性就是Illuminate\View\Engines\EngineResolver
類的物件,我們看它的resolve
方法:
還記得,我們在上面呼叫了它的register
方法:
所以我們呼叫register
方法會得到Illuminate\View\Engines\CompilerEngine
類的物件,我們再一次回到\Illuminate\View\Factory類
的viewInstance
方法中,這裡我們在Illuminate\View\View
類的建構函式中初始化了它的$engine
屬性。
明白了這個之後,我們可以再次回到Illuminate\View\View
類的getContents
方法了:
這裡我簡要的和大家說下gatherData
方法,這個方法合併我們直接傳遞給檢視的資料和我們的共享資料,共享資料是啥呢?還記不記得這個方法呼叫:
這個資料會在所有的模板中共享(看你的呼叫),gatherData
方法的作用就是如此。
不多說,進入到Illuminate\View\Engines\CompilerEngine
類的get
方法:
它的程式碼首先就是判斷當前檢視是否過期,如果過期的話,就重新編譯檢視檔案,關於檢視檔案的編譯,我們在下週再來仔細講,這裡我們看看$compiler
:
所以他就是Illuminate\View\Compilers\BladeCompiler
,關於Blade引擎,我們在下一篇部落格中講。
經過Blade引擎的編譯,我們就得到了檢視檔案的內容,我們回到Illuminate\View\View
類的render
方法中,檢視渲染的核心操作就算完成了,接下來的操作就和老司機帶你深入分析 Laravel 響應之一中的一模一樣了。
總結
作為Laravel檢視系列的第一篇,希望大家仔細閱讀,困難肯定是有的,但是讀懂之後的喜悅也是無以言表的,加油。鄙人有個qq群,可以交流,也可以加我的微信,下方有,qq群如下:
本作品採用《CC 協議》,轉載必須註明作者和本文連結