這篇文章主要介紹ThinkPHP中模板引擎是什么,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

模板引擎由來
早期做PHP開發(fā)WEB應(yīng)用都是把PHP代碼和HTML模板混在一起,模板引擎的誕生主要就是為了解決后端與前端的完全分離(現(xiàn)在來看其實(shí)是屬于不完全分離)的問題,讓開發(fā)與美工可以分工合作(雖然實(shí)際上最終模板工作大多仍然是由后端開發(fā)人員完成),從而提高開發(fā)效率和便于維護(hù)。
伴隨著PHP的快速成長,模板引擎也越來越多,但大致分為解釋型和編譯型兩種,目前主流的模板引擎大多數(shù)是編譯型的,也就是會(huì)先把模板編譯成PHP文件執(zhí)行,只要模板文件本身不變化,就不需要重新編譯,例如老牌的Smarty。解釋型的模板引擎每次執(zhí)行的時(shí)候都會(huì)進(jìn)行模板解析流程,例如小強(qiáng)(tinybutstrong)。
ThinkPHP從一開始就內(nèi)置了一個(gè)基于XML標(biāo)簽庫技術(shù)的編譯型模板引擎,早期參考自Struts,并且不斷在汲取新的思想不斷進(jìn)化。
如何選擇模板引擎
目前主流框架都帶有模板引擎組件或者封裝了模板引擎的實(shí)現(xiàn),因此選擇內(nèi)置的解決方案是很好之選,功能和穩(wěn)定性都有保證。目前最流行的模板引擎當(dāng)屬Laravel自帶的Blade模板引擎,以及Symfony自帶的Twig模板引擎。
通過安裝模板引擎擴(kuò)展,你可以在ThinkPHP中輕松使用包括Angular、Twig和Blade在內(nèi)的模板引擎,甚至完全不使用模板引擎而是直接用PHP文件作為模板。
因?yàn)榻鼛啄耆笄岸丝蚣埽≧eact/Vue/Angular)的流行,前后端分離開發(fā)逐漸成為主流,因此從ThinkPHP5.0開始定位為API開發(fā)而設(shè)計(jì),導(dǎo)致模板引擎的概念已經(jīng)被弱化了。ThinkPHP5.1版本的模板引擎進(jìn)行過一次內(nèi)部的重構(gòu),使得模板標(biāo)簽更加易用和接近PHP語法。
至少對(duì)于大部分新的應(yīng)用來說,應(yīng)該選擇更主流的前后端分離設(shè)計(jì),盡量減輕服務(wù)端的壓力,也更方便前后端單獨(dú)測試。你會(huì)在市面上不經(jīng)意的看到采用Vue和ThinkPHP的產(chǎn)品(之前幾期的ThinkPHP開發(fā)者周刊曾經(jīng)報(bào)道過幾個(gè))。如果是維護(hù)一些老項(xiàng)目尤其是內(nèi)容管理產(chǎn)品的時(shí)候,仍然可能會(huì)用到模板引擎。
鑒于這種情況,下一個(gè)版本的ThinkPHP框架將不會(huì)內(nèi)置模板引擎,但有需要使用模板引擎的開發(fā)者仍然可以使用官方獨(dú)立出來的think-template類庫,具體使用可以參考這篇文章。
后面的篇幅,我們主要來總結(jié)下ThinkPHP內(nèi)置的模板引擎的使用和技巧。
模板執(zhí)行流程
系統(tǒng)內(nèi)部的模板引擎調(diào)用關(guān)系如下:
視圖(View) <=> 模板驅(qū)動(dòng)(Driver) <=> 模板引擎(Template)
視圖和模板引擎之間增加了一個(gè)驅(qū)動(dòng)層,所以可以很方便的替換其它的模板引擎。通常我們?cè)诳刂破髦姓{(diào)用的assign/fetch等方法其實(shí)都是調(diào)用的think\View類的方法。當(dāng)然,如果有必要,你也完全可以直接在控制器中操作模板引擎類,只是不方便切換其它模板引擎。
以fetch方法為例,我們看下最終的調(diào)用過程:
think\Controller->fetch(); think\View->fetch(); think\view\driver\Think->fetch(); think\Template->fetch();
如果你調(diào)用fetch方法的時(shí)候沒有傳入要渲染的完整模板文件名,則會(huì)在第三步的時(shí)候自動(dòng)識(shí)別要渲染的模板文件。
很顯然,最關(guān)鍵是最后一步,模板編譯和執(zhí)行的流程則全部由
think\Template->fetch();
方法完成,這個(gè)環(huán)節(jié)大體又可以分成幾個(gè)流程。
1、判斷和讀取頁面渲染緩存
如果當(dāng)前模板設(shè)置了頁面輸出緩存并且已經(jīng)渲染輸出過,如果是則會(huì)讀取緩存中的輸出內(nèi)容直接輸出。
if (!empty($this->config['cache_id']) && $this->config['display_cache']) {
// 讀取渲染緩存
$cacheContent = $cache->get($this->config['cache_id']);
if (false !== $cacheContent) {
echo $cacheContent;
return;
}
}2、定位模板文件
定位實(shí)際的模板文件操作由模板引擎類的parseTemplateFile方法實(shí)現(xiàn),這個(gè)方法的邏輯其實(shí)和視圖驅(qū)動(dòng)類的parseTemplate方法是類似的,如果最終的模板文件不存在則會(huì)拋出一個(gè)模板文件不存在的異常。
$template = $this->parseTemplateFile($template);
3、判斷編譯緩存
如果當(dāng)前的模板文件已經(jīng)編譯過,會(huì)判斷緩存是否還有效,有效的話就不用重復(fù)解析直接讀取緩存的解析內(nèi)容。由checkCache方法負(fù)責(zé)完成。
if (!$this->checkCache($cacheFile)) {
// 緩存無效 重新模板編譯
$content = file_get_contents($template);
$this->compiler($content, $cacheFile);
}4、模板編譯并緩存
這一步驟是模板引擎最核心的環(huán)節(jié),也是功能最復(fù)雜的地方,由compiler方法負(fù)責(zé)完成,主要是解析當(dāng)前模板文件中的模板標(biāo)簽語法為PHP可執(zhí)行代碼,然后生成一個(gè)模板解析緩存文件,也就是所謂的模板“編譯”,其中使用了大量的正則表達(dá)式替換技術(shù),雖然正則解析有一定的性能開銷,但得益于一次解析多次調(diào)用的緩存原理,基本上模板解析的性能開銷不會(huì)影響實(shí)際使用的性能。
模板編譯方法的關(guān)鍵代碼是parse方法,parse方法負(fù)責(zé)對(duì)模板文件中的標(biāo)簽進(jìn)行解析,然后寫入編譯緩存文件,編譯緩存默認(rèn)使用的是文件緩存,支持?jǐn)U展。
5、讀取編譯緩存
模板編譯的過程只是生成了模板編譯緩存文件,并沒有真正載入模板,這一步驟就是載入模板編譯緩存,然后導(dǎo)入模板變量。實(shí)現(xiàn)方法可以參考think\template\driver\File類的read方法。
public function read($cacheFile, $vars = [])
{
$this->cacheFile = $cacheFile;
if (!empty($vars) && is_array($vars)) {
// 模板陣列變量分解成為獨(dú)立變量
extract($vars, EXTR_OVERWRITE);
}
//載入模版緩存文件
include $this->cacheFile;
}6、緩存頁面輸出
如果當(dāng)前模板渲染的時(shí)候開啟了頁面輸出緩存,就會(huì)這一步生成頁面渲染后的輸出緩存。
模板編譯原理
我們來了解下ThinkPHP的模板引擎的實(shí)現(xiàn)原理。前面提到過,ThinkPHP的模板引擎最早源于Struts的設(shè)計(jì)理念,基于XML和標(biāo)簽庫的技術(shù)實(shí)現(xiàn)。在設(shè)計(jì)模板語言的時(shí)候使用系統(tǒng)固定的標(biāo)簽來實(shí)現(xiàn)普通的變量輸出功能(所以稱之為普通標(biāo)簽),而利用XML標(biāo)簽庫技術(shù)實(shí)現(xiàn)的動(dòng)態(tài)標(biāo)簽用于變量的控制或者條件判斷輸出。
普通標(biāo)簽的解析是由think\Template類的parseTag方法完成的,主要實(shí)現(xiàn)了下面幾個(gè)模板功能:
·變量輸出(包括系統(tǒng)變量);
·函數(shù)過濾;
·變量運(yùn)算;
·三元運(yùn)算;
·執(zhí)行函數(shù)以及輸出結(jié)果;
·模板注釋。
標(biāo)簽庫采用的是動(dòng)態(tài)擴(kuò)展的設(shè)計(jì)方案,采用了類似XML的閉合/開放定義方式(這個(gè)其實(shí)也是目前模板引擎的一個(gè)局限所在),例如下面的這個(gè):
// 閉合類型標(biāo)簽 <tagLib:tagName name="value" > ... </tagLib:tagName> // 開放類型標(biāo)簽 <tagLib:tagName name="value" />
tagLib就代表了一個(gè)標(biāo)簽庫(類),后面的tagName標(biāo)簽就表示該標(biāo)簽庫下面的某個(gè)標(biāo)簽(通常對(duì)應(yīng)了標(biāo)簽庫類的某個(gè)方法),后面的屬性就是該標(biāo)簽支持的屬性定義。具體該標(biāo)簽的屬性和功能則完全由標(biāo)簽庫類的這個(gè)方法來決定。
可以在模板開頭明確指出,當(dāng)前模板使用了哪些標(biāo)簽庫
{taglib name="html,article" /}所以要擴(kuò)展模板引擎的功能只需要通過擴(kuò)展一個(gè)標(biāo)簽庫類就可以了。大多數(shù)的內(nèi)容管理系統(tǒng)都會(huì)定義一套自己的模板二次開發(fā)標(biāo)簽,利用標(biāo)簽庫功能就可以很方便的定義一套屬于自己的標(biāo)簽功能。
系統(tǒng)內(nèi)置了一套標(biāo)簽庫Cx,主要用于文件包含、條件控制、循環(huán)輸出等功能。內(nèi)置標(biāo)簽庫在使用的時(shí)候無需引入,而且在使用的時(shí)候可以省略標(biāo)簽庫前綴,例如:
{foreach $list as $key=>$vo }
{$vo.id}:{$vo.name}
{/foreach}這個(gè)模板語法相信PHP開發(fā)的很容易上手,上面的標(biāo)簽解析由think\template\taglib\Cx類的tagForeach方法完成,該方法的返回值是一個(gè)字符串,其實(shí)就是最終會(huì)解析成的一段包含變量的PHP可執(zhí)行代碼。
到這里,模板引擎的執(zhí)行過程和原理現(xiàn)在基本就明白了,剩下的就是模板標(biāo)簽的解析細(xì)節(jié),考驗(yàn)的就是正則表達(dá)式的掌握程度了。本文就不做深入了,有興趣的朋友可以去看一些正則表達(dá)式的相關(guān)資料(例如這本《正則指引》,開發(fā)者周刊第14期也提供了一些在線的正則工具)。
遵循的原則
使用模板引擎,要盡量遵循幾個(gè)重要的原則。
不要在模板文件中添加任何的業(yè)務(wù)邏輯
模板的作用主要是進(jìn)行模板變量的控制和輸出,不要在模板文件中添加業(yè)務(wù)邏輯代碼。
明確指定渲染模板
養(yǎng)成明確指定渲染模板的好習(xí)慣,避免當(dāng)方法名發(fā)生變化,或者被其它方法調(diào)用的時(shí)候發(fā)生錯(cuò)誤。也不易受模板命名規(guī)范的影響。
變量統(tǒng)一賦值
使用assign方法或者在view助手函數(shù)的時(shí)候,統(tǒng)一一次傳入模板變量。不要多次賦值,以免混亂。
系統(tǒng)變量無需賦值到模板
對(duì)于系統(tǒng)變量(包括請(qǐng)求變量、$_SESSION和$_SERVER等系統(tǒng)變量)無需進(jìn)行模板變量賦值,可以直接在模板中輸出。
常見問題
這里總結(jié)一下經(jīng)常會(huì)遇到的一些常見問題。
修改定界符
可以通過模板配置文件修改模板標(biāo)簽的定界符。
例如,修改普通標(biāo)簽定界符
'tpl_begin' => '{{', // 模板引擎普通標(biāo)簽開始標(biāo)記
'tpl_end' => '}}', // 模板引擎普通標(biāo)簽結(jié)束標(biāo)記標(biāo)簽庫標(biāo)簽定界符
'taglib_begin' => '<{', // 標(biāo)簽庫標(biāo)簽開始標(biāo)記
'taglib_end' => '}>', // 標(biāo)簽庫標(biāo)簽結(jié)束標(biāo)記保持原樣輸出
如果擔(dān)心模板標(biāo)簽和JS代碼產(chǎn)生混淆,可以使用literal標(biāo)簽
{literal} Hello,{$name}! {/literal}頁面最終會(huì)直接輸出
Hello,{$name}!避免輸出轉(zhuǎn)義
5.1版本為了避免XSS攻擊,默認(rèn)對(duì)模板變量的輸出使用了安全轉(zhuǎn)義,默認(rèn)的轉(zhuǎn)義函數(shù)是htmlentities,你可以通過更改default_filter配置改變默認(rèn)的轉(zhuǎn)義函數(shù)。
如果你不需要對(duì)某個(gè)模板變量輸出進(jìn)行轉(zhuǎn)義(例如包含了HTML代碼),可以使用:
{$data.content|raw}分頁輸出就是一個(gè)需要輸出HTML的典型例子,因此必須增加|raw。
關(guān)于模板主題
新版取消了原來的模板主題功能,因?yàn)槟0逯黝}對(duì)模板引擎來說,其實(shí)無非是一個(gè)模板目錄,完全可以根據(jù)自己的需求控制。
例如
$theme = 'blue';
$this->fetch('/' . $theme. '/user/index');或者動(dòng)態(tài)設(shè)置模板引擎的view_path參數(shù)
$this->view->config('view_path', \think\facade\App::getModulePath(). 'view/'. $theme . '/');如何關(guān)閉模板緩存
由于是編譯型模板引擎,模板標(biāo)簽不能被直接執(zhí)行,必須編譯成PHP語法后才能執(zhí)行,因此不能關(guān)閉模板編譯緩存,模板引擎每次執(zhí)行渲染的時(shí)候會(huì)檢測模板文件是否有變化,當(dāng)模板文件的修改時(shí)間超過模板編譯緩存的修改時(shí)間后,模板引擎會(huì)自動(dòng)更新編譯緩存。
但你可以強(qiáng)制模板引擎每次都重新編譯,只需要在配置文件中設(shè)置
'tpl_cache' => false, // 關(guān)閉模板緩存
使用PHP作為模板引擎
如果不希望使用內(nèi)置的模板引擎,直接使用PHP作為模板引擎,可以配置
'type' => 'php',
配置使用PHP作為模板引擎的話,是不會(huì)生成模板編譯緩存的。
如何使用第三方模板引擎
系統(tǒng)支持?jǐn)U展其它的第三方模板引擎,你只需要開發(fā)一個(gè)模板引擎驅(qū)動(dòng),目前已經(jīng)支持的第三方模板引擎包括Smarty、Twig和Blade。
如何跨模塊輸出模板
要渲染一個(gè)跨模塊的模板文件,你需要使用
// 渲染user模塊的模板文件
$this->fetch('User@order/index');是否支持變量運(yùn)算
可以直接在模板文件中進(jìn)行變量運(yùn)算而不需要在控制器中進(jìn)行運(yùn)算后再賦值都模板變量輸出。
{$score1+$score2}
{$count++}文件包含是否支持變量
include標(biāo)簽可以支持傳入變量,但只能使用
{include file="$file" /}而不能使用
{include file="file_$name" /}可以支持模板輸出替換么
支持兩個(gè)方式對(duì)模板進(jìn)行輸出替換,如果需要對(duì)模板文件的內(nèi)容進(jìn)行替換,可以配置:
'tpl_replace_string' => [ '__STATIC__'=>'/static', '__JS__' => '/static/javascript', ]
如果是對(duì)模板渲染輸出的內(nèi)容進(jìn)行替換,可以在控制器中使用視圖過濾功能:
public function index()
{
// 使用視圖輸出過濾
return $this->filter(function($content){
return str_replace("\r\n",'<br/>',$content);
})->fetch();
}模板繼承的block是否支持嵌套
目前模板繼承的block無法支持嵌套功能,你應(yīng)該使用其它方式解決。
以上是“ThinkPHP中模板引擎是什么”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
分享標(biāo)題:ThinkPHP中模板引擎是什么-創(chuàng)新互聯(lián)
轉(zhuǎn)載源于:http://www.chinadenli.net/article8/dhdsip.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)、網(wǎng)站營銷、營銷型網(wǎng)站建設(shè)、企業(yè)網(wǎng)站制作、關(guān)鍵詞優(yōu)化、靜態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容