Laravel 大將之 View 模塊

本文是基於Laravel 5.4版本的View模塊代碼進行分析書寫;php

文件結構

View模塊的文件格局及功能以下圖所示:
圖片描述css

視圖化呈現時的大概流程:html

  1. 經過view()方法的調用,開始視圖的呈現;
  2. 首先,查找視圖文件;
    (1)依次遍歷路徑,若是文件名帶命名空間(也就是::以前的部分),則採用命名空間對應註冊的路徑數組,不然採用全局路徑數組(在Illuminate\View\FileViewFinder類中的paths變量);
    (2)結合當前路徑,文件名,後綴名(默認順序是blade.phpphpcss),判斷文件是否存在;
    (3)若是文件不存在,報異常:對應的view文件不存在;若是文件存在,則根據後綴名調用對應的引擎進行解析;
  3. 若是是css後綴,採用file引擎,核心調用方法是file_get_contents;
  4. 若是是php後綴,採用php引擎,核心調用方法是前端

    ob_start();
    include $__path;
    ob_get_clean();
  5. 若是是blade.php後綴,採用blade引擎;
    這個引擎會主動做緩存處理,若是緩存文件未過時,則直接調用緩存文件,不然從新編譯,並經過sha1生成緩存文件(位於storage/framework/views目錄下);

Blade 引擎編譯

Blade引擎對文件的編譯,是經過大量的正則匹配和替換實現的;laravel

protected $compilers = [ 
    'Comments',   // 註釋部分
    'Extensions', // 擴展部分
    'Statements', // 語句塊 (@ 開頭的指令)
    'Echos',      // 輸出
];

protected function parseToken($token) {
    list($id, $content) = $token;
    
    if ($id == T_INLINE_HTML) {
        foreach ($this->compilers as $type) {
            $content = $this->{"compile{$type}"}($content);
        }
    }
}

在解析的過程當中,Blade會先使用token_get_all函數獲取視圖文件中的被PHP解釋器認爲是HTMLT_INLINE_HTML)的部分,而後依次進行CommentsExtensionsStatementsEchos部分的正則替換;segmentfault

註釋部分
核心代碼以下,將註釋符號「{{-- --}}」包裹的代碼替換爲空字符串;數組

preg_replace("/{{--(.*?)--}}/s", '', $value);

擴展部分
經過extend方法向BladeCompiler添加自定義處理的回調函數,對模板內容進行自定義的文本匹配替換;緩存

核心代碼在Illuminate\View\BladeCompiler文件中,以下:app

// 自定義的文本替換擴展 數組
protected $extensions = [];

protected function compileExtensions($value) {
    foreach ($this->extensions as $compiler) {
        $value = call_user_func($compiler, $value, $this);
    }
    
    return $value;
}

指令替換
這部分就是將相似@if這種框架自帶的指令和經過directive方法註冊的指令進行文本替換;框架

框架提供的指令有如下十部分:

  • View\Compilers\Concerns\CompilesAuthorizations: 權限檢查
    指令包括:@can@cannot@elsecan@elsecannot@endcan@endcannot
  • Concerns\CompilesComponents:與組件、插槽相關
    指令包括:@component@endcomponent@slot@endslot
  • Concerns\CompilesConditionals:與判斷語句相關
    指令包括:@if@unless@else@elseif@endif@endunless@isset@endisset@hassection
  • Concerns\CompilesIncludes:嵌入文件
    指令包括:@each@include@includeif@includewhen
  • Concerns\CompilesInjections:服務注入
    指令包括:@inject
  • Concerns\CompilesLayouts:和佈局相關
    指令包括:@extends@section@parent@yield@show@append@overwrite@stop@endsection
  • Concerns\CompilesLoops:與循環相關
    指令包括:@forelse@empty@endforelse@endempty@for@foreach@break@continue@endfor@endforeach@while@endwhile
  • Concerns\CompilesRawPhp:與原生PHP語句相關
    指令包括:@php@endphp@unset
  • Concerns\CompilesStacks:和堆棧相關
    指令包括:@stack@push@endpush@prepend@endprepend
  • Concerns\CompilesTranslations:與本地化翻譯相關
    指令包括:@lang@endlang@choice

Echo 替換
echo輸出是針對{!! !!}{{ }}{{{ }}}三種括號進行正則替換;

  • {!! !!}輸出未轉義字符,用於輸出原生帶html標籤的值;
  • {{ }}正常輸出,支持三目運算符替換;
  • {{{ }}}輸出轉義字符,支持三目運算符替換;

三目運算符替換是指:{{ $a ?: "默認值" }} (或者 {{$a or "默認值"}}) 換成 {{ isset($a) ? $a : "默認值"}}

參考文章

相關文章
相關標籤/搜索