標籤:使用 io strong 檔案 ar 問題 cti 代碼 html
引子:今天遇到一個問題,模板中某些變數有時候沒有定義,如果php開啟了E_ALL報錯層級,那麼會出現一個notice,提示變數未定義。
一開始的想法是通過三元運算式( )來給每個變數設定一個預設值,後來發現這種寫法太繁瑣,而且與volt標籤格格不入。
再後來想到屏蔽E_NOTICE報告,但開發環境下還是很不恰當的。
最後發現volt引擎有一個過濾器Filters功能,解決了這個問題,寫法如:{{ var|default(‘str‘) }} ,在$var為空白的時候,將會將該處設定為str,當然,str可以是Null 字元串。
本文就探究一下什麼是過濾器,以及如何自訂過濾器。
第一,模板渲染的是什嗎?
在使用volt模板引擎的時候,模板是如何渲染的呢?大家都知道,在控制器方法執行完畢後,架構會自動渲染視圖View,而這時候由於你使用了volt模板引擎,裡面特有的一套標籤文法並非php文法,所以視圖無法直接include模板檔案而作為php指令碼解釋。這時候視圖會做一件事情,它會先將模板代碼中的標籤替換為php代碼,儲存到模板快取檔案中,緩衝位置是你在di中配置視圖的時候自己設定的,每個快取檔案都對應一個模板檔案,第二次渲染視圖的時候將直接取快取檔案,避免了每次都要解析volt標籤,所以效能上與原生php模板並無差距,某些情況下可能更好(布局以及模板繼承時,會將多層模板合并為一個,減少了檔案讀取次數)。
第二,標籤‘原形‘
{{ var|default(‘str‘) }}究竟被轉化為什嗎?我們可以通過觀察模板緩衝看到,這個標籤大概被轉化為
<?php echo (empty($var) ? (‘str‘) : ($var)); ?>
第三,理解管道‘|‘
熟悉shell的朋友這一步一眼瞭然,標籤的作用機制是:將$var的值傳給下一個過濾器default處理,過濾器還可附加其他參數,只要如同函數調用一樣增加參數即可,如上的 (‘str‘);變數類型的標籤最終會轉化為echo語句。
第四,自訂過濾器
通過官方手冊可以知道,在di中註冊volt模板引擎的時候,可以添加自訂的filter方法,先看一段代碼:
//volt模板引擎服務$di->set(‘voltService‘, function($view, $di) { $volt = new \Phalcon\Mvc\View\Engine\Volt($view, $di); $volt->setOptions(array( "compiledPath" => APP_PATH."/runtime/volt/", "compiledExtension" => ".compiled" )); //自訂過濾器 $compiler = $volt->getCompiler(); $compiler->addFilter(‘int‘, function($resolvedArgs, $exprArgs) { return ‘intval(‘ . $resolvedArgs . ‘)‘; }); return $volt;});
上面我們首先通過getCompiler拿到"編譯器對象”$compiler,在$compiler中通過addFilter添加自訂的過濾器,上面的代碼添加了一個叫做 “int” 的過濾器,其作用是將$var的值轉化為整形。
第五,理解
當volt模板解析的時候,假如有一個標籤{{ var|int }},這時候$compiler會檢查對象中有沒有int過濾器,顯然是有的,那麼會調用匿名函數,將傳回值字串放到echo 中,如上定義的int過濾器,最終返回的就是 intval($val),該標籤最終被替換為
<?php echo intval($val);?>
之後交由PHP解釋並返回html代碼到瀏覽器。
細節:$resolvedArgs是什嗎?
它是變數名和附加參數的拼接,比如上面int沒有附加參數,那麼它的值就是 ‘$var‘,注意這裡是原義字串,不要當成變數。
假設我們定義了一個過濾器 trim,我們想要 {{ var|trim(‘%‘) }}的結果為 trim($val,‘%‘)的值,那麼在定義過濾器匿名函數的時候就需要這麼寫
$compiler->addFilter(‘concat‘, function($resolvedArgs, $exprArgs) { return ‘trim(‘.$resolvedArgs.‘)‘;});return $volt;
也就是$resolvedArgs這個變數的值是:$val,‘%‘ 注意,這裡是原義字串,為了表示方便,省略了兩邊的單引號,$var變數名永遠在開頭。
最終標籤被替換為php代碼:<?php echo trim($val,‘%‘);?>
那麼$exprArgs是什麼呢?它是一個數組,儲存了每個參數的類型、原義字串、所屬指令碼等等,一般用不到,不過特殊情況下可能使用,比如內建的 default過濾器,在 default(‘‘) 指定參數的時候,返回的是 empty($var)?‘‘:$var 這裡就需要從$exprArgs得到每個參數的資訊。
自訂模板函數也是同樣的原理,目的都是將標籤轉換為php代碼,並儲存到模板緩衝中。
感言:
模板引擎並不神秘,只要理解其工作機制,代碼實現原理,每個人都能實現自己的模板引擎。
phalcon模板引擎(volt)自訂過濾器