Laravel 視圖模塊運行流程


提示:

vendor\laravel\framework\src\Illuminate\View是視圖模塊所在的文件夾,如未說明類所在文件位置則指此文件夾。

1. 服務提供者類注入相關類到容器

在使用視圖相關的功能之前是需要做些准備的,准備自然是在服務提供者類運行的(在app\config.php的providers中定義了應用中的服務提供者類),從中我們可以看出Illuminate\View\ViewServiceProvider::class指的就是ViewServiceProvider類,因此在ViewServiceProvider類中會注冊一些需要用到的依賴到容器,注入名稱和實例如下:

view.engine.resolver  EngineResolver
    php               PhpEngine
    blade             CompilerEngine
blade.compiler        BladeCompiler
view.finder           FileViewFinder
view                  Factory
file
這個時候我們已經可以看出Factory是視圖模塊重要的類了,因為Laravel會從容器中取出view.engine.resolver, view.finder, events(這個類是其他地方注入到容器中的)中的對象作為參數傳遞給Factory,而php和blade雖然並沒有注入到容器,卻是作為EngineResolver的屬性$resolvers的值的。

2.開始使用視圖

上一步驟只是做了些視圖運行前的准備,而並沒有真的運行視圖的功能,一般運行是從view()開始的,這是一個全局的方法,這個方法是定義在vendor\laravel\framework\src\Illuminate\Foundation\helpers.php中的,這里其實調用了Factorymake(),這個方法其實主要是對傳入的參數做處理並用這些參數初始化View類,再返回View的實例。

$this->callCreator($view = new View($this, $this->getEngineFromPath($path), $view, $path, $data));
return $view;

View的處理還涉及到RouterResponse的處理,不理會這個我們是知道視圖其實返回的應該是字符串的才對。對象轉字符串自然使用的是魔術方法__toString(),這里並不直接返回字符串,而是通過一系列的調用最終是在getContents()中返回$this->engine->get(),這里的engine是CompilerEngine,即上面View實例化的時候傳遞的第二個參數(也是EngineInterface的實現),因為Laravel的視圖文件的名稱包含blade,所以實例化的是CompilerEngine。事實上這和容器中名為view.engine.resolver的類實例有關,具體細節可以在getEngineFromPath()中找。

3.模版的編譯

CompilerEngine$compiler才是實際把視圖文件轉成字符串的主力。一般的$compiler的實例是BladeCompiler,這個就是把Blade語法(Blade是Laravel內置模版引擎的名字)轉換成PHP語法的核心。

不管上面的步驟如何的繞來繞去,把視圖文件編譯成字符串才是BladeCompiler類的主場功能,這個類才是真正的苦力工作者。BladeCompiler實現了CompilerInterface接口,這個接口真正工作是compile()compile()把視圖文件編譯成PHP的原生語法的字符串並寫入到緩存目錄的文件中,而getCompiledPath()根據視圖文件的路徑來獲取編譯后的文件的路徑。

編譯使用token_get_all()來進行語法的解析,當碰到PHP標記為T_INLINE_HTML(T_INLINE_HTML標記其實就是code無法直接解析成PHP而把這段code當作一段嵌套的HTML,這里一般就是指Blade語法的Code)的PHP標記時用對應的方法進行語法的替換,直到最終沒有PHP標記為T_INLINE_HTML為止。

無法直接編譯的code分為4類,分別是擴展,語句,注釋,輸出,這個從$compilers中可以看出,我們可以稱$compilers為內部編譯器,每個內部編譯器對應一個相應的解析方式,如注釋編譯器對應compileComments()

/**
 * Compile Blade comments into valid PHP.
 *
 * @param  string  $value
 * @return string
 */
protected function compileComments($value)
{
    $pattern = sprintf('/%s--((.|\s)*?)--%s/', $this->contentTags[0], $this->contentTags[1]);

    return preg_replace($pattern, '<?php /*$1*/ ?>', $value);
}


這里就把Blade語法的code{{-- This comment will not be present in the rendered HTML --}}變成原生PHP語法的code<?php /*This comment will not be present in the rendered HTML*/ ?>了。 從中不難看出就是把Blade語法翻譯成PHP原生語法的實現。當然這是最簡單的內部編譯器,像語句,輸出內部編譯器的實現就復雜的多,但只是實現復雜,涉及到正則的解析和不同形式的語句的解析,原理還是一樣的。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM