PHP開發(fā)必備 PHP模版引擎Dwoo深入學(xué)習(xí)
在上一篇關(guān)于Dwoo的教程中(PHP開發(fā)必備 一步步學(xué)PHP模版引擎Dwoo),我們討論了Dwoo中的基本用法。在本文中,我們將進(jìn)一步講解在Dwoo中的一些高級用法,比如插件機制的編寫以及如何跟常見的PHP框架整合。
一、Dwoo中模版的繼承
Dwoo的其中一個強大功能是它可以支持模版的繼承。這實現(xiàn)起來是十分簡單的,只需要定義好一個父模版,然后子模版則可以繼承父模版了,并且可以在子模版中定義多種新的特性。聰明的開發(fā)者會善于利用這個特性,去減少重復(fù)的勞動。
Dwoo中繼承模版的關(guān)鍵在于“擴(kuò)展”的插件機制,它允許模版去繼承另外一個模版。為了更好地理解這一特性,我們舉個例子說明如下。假設(shè)目前你已經(jīng)有一個基類的模版,名字叫base.tpl,其中包含了兩個區(qū)域,一個是導(dǎo)航區(qū),一個是內(nèi)容區(qū),如下:
- <html>
- <head></head>
- <body>
- {block "nav"}
- {/block}
- {block "content"}
- <div id="content">
- This is content for the main page.
- </div>
- {/block}
- </body>
- </html>
現(xiàn)在,假設(shè)你的一些頁面需要使用水平導(dǎo)航條,你只需要繼承基類模版頁即可,并且可以重新定義導(dǎo)航條的樣式,如下代碼,我們把這個代碼定義為child.tpl:
- {extends "base.tpl"}
- {block "nav"}
- <div id="nav">
- <a href="#">Home</a> |
- <a href="#">News</a> |
- <a href="#">Weather</a> |
- <a href="#">Hotels</a> |
- <a href="#">Dining</a>
- </tr>
- </table>
- </div>
- {/block}
這里使用了{(lán)extends “base.tpl”}指出是繼承了父類的模版,并且在這里的{block “nav”}區(qū)域中,重寫了導(dǎo)航條的內(nèi)容,最后輸出為如下圖:
現(xiàn)在我們考察另外一種情況,假設(shè)一些頁面中需要額外的子導(dǎo)航菜單,比如需要以垂直形式顯示導(dǎo)航條,這時,我們可以采用如下代碼:
- {extends "child.tpl"}
- {block "nav"}
- {$dwoo.parent}
- <div id="sub-nav">
- <h2>{$subtitle}</h2>
- <ul>
- {loop $items}
- <li><a href="#">{$item}</a></li>
- {/loop}
- </ul>
- </div>
- {/block}
- {block "content"}
- <div id="content">
- This is content for the Dining page.
- </div>
- {/block}
在這里,使用了{(lán)$dwoo.parent}去調(diào)用了父類模版,注意這里是繼承了child.tpl這個模版,也就是說,調(diào)用了父類模版中的導(dǎo)航條中的內(nèi)容,并且這里又重新定義了一個垂直的導(dǎo)航條,注意這里還重寫了content區(qū)域的內(nèi)容,覆蓋了父模版中對應(yīng)的content區(qū)域的內(nèi)容了,結(jié)果如下圖:
可以看到,只要適當(dāng)使用模版繼承,則可以大大方便開發(fā)。
#p#
二、子模版
Dwoo支持子模版,這些子模版使得開發(fā)者可以在應(yīng)用中重用它們。子模版的創(chuàng)建方法是使用標(biāo)簽{template}….{/template},其中要提供唯一的名稱,以便在其他地方進(jìn)行引用。而在其他地方引用子模版,可以使用”load template”標(biāo)簽加載。
子模版中可以傳遞多個參數(shù),下面直接看例子以方便理解。首先編寫一個子模版,名稱叫slave.tpl,代碼如下:
- {template mylist data}
- <ul>
- {foreach $data d}
- <li>{$d}</li>
- {/foreach}
- </ul>
- {/template}
這里,我們把這個子模版命名為mylist,其中有一個循環(huán)取讀取data變量中的值并輸出。
有了子模版后,我們就可以在需要其的地方加載它,比如,在一個模版文件master.tpl中,可以這樣調(diào)用:
- {load_templates "slave.tpl"}
- {mylist $items}
這里用load_templates加載slave.tpl的子模版,并且為子模版mylist賦值items變量,而items變量可以由如下代碼去賦值:
- <?php
- include 'dwooAutoload.php';
- try {
- $dwoo = new Dwoo();
- $tpl = new Dwoo_Template_File('tmpl/master.tpl');
- $data = array();
- $data['items'] = array('red', 'blue', 'green', 'yellow');;
- $dwoo->output($tpl, $data);
- } catch (Exception $e) {
- echo "Error: " . $e->getMessage();
- }
- ?>
可以看到輸出如下:
可以看到,子模版的確十分方便使用,而且子模版中的內(nèi)容一旦變更,其他所有用到子模版地方的內(nèi)容也會接著變化。
#p#
三、編寫自己的插件
Dwoo中的一個前大功能是能可以讓開發(fā)者編寫插件,并通過Dwoo的addplugin機制加載自己寫的類,現(xiàn)舉一個簡單例子說明。比如下面的代碼,封裝了對email的操作:
- <?php
- function fix_address(Dwoo $dwoo, $str) {
- return str_replace(
- array('@', '.', '-'),
- array(' at ', ' dot ', ' dash '),
- $str
- );
- }
- include 'dwooAutoload.php';
- try {
- $dwoo = new Dwoo();
- $tpl = new Dwoo_Template_File('tmpl/plugin.tpl');
- $dwoo->addPlugin('email_safe', 'fix_address');
- $data['string']= 'vikram@example.com';
- $dwoo->output($tpl, $data);
- } catch (Exception $e) {
- echo "Error: " . $e->getMessage();
- }
- ?>
在這個例子中,我們想將用戶EMAIL中的象@,分隔符等符號用英文替換掉,這樣防止象網(wǎng)上機器人等去采集EMAIL,泄露私隱。其中fix_address方法為替換的方法。而通過dwoo中的addPlugin方法,命名一個插件,名字為email_safe,而插件的內(nèi)容則指定為fix_address方法。在使用這個插件時,可以如下使用,plugin.tpl內(nèi)容為:
- {email_safe($string)}
下圖為輸出結(jié)果:
而另外一種使用dwoo插件的方法為繼承Dwoo_Filter abstract class,如下:
- <?php
- class Dwoo_Plugin_email_safe extends Dwoo_Plugin
- {
- public function process($email)
- {
- return str_replace(
- array('@', '.', '-'),
- array(' at ', ' dot ', ' dash '),
- );
- }
- }
- ?>
如果用這種方式的話,則可以把該文件保存在dwoo目錄下的plugins目錄下,則dwoo的自動加載機制會自動加載這個插件,而不用每次使用時都使用addplugin的功能。
#p#
四、DWOO的過濾器
同樣,dwoo中也支持用戶編寫過濾器,它可以在模版內(nèi)容向用戶輸出前進(jìn)行一些相關(guān)的操作,跟插件類似,可以使用addFilter()加載自己編寫的過濾器,例子如下:
- <?php
- function activate_mailto_links(Dwoo $dwoo, $str) {
- return preg_replace('/([a-zA-Z0-9]+@[a-zA-Z0-9._-]+\.[a-zA-Z]+)/', '<a href="mailto:$1">$1</a>', $str);
- }
- include 'dwooAutoload.php';
- try {
- $dwoo = new Dwoo();
- $dwoo->addFilter('activate_mailto_links');
- $tpl = new Dwoo_Template_File('tmpl/filter.tpl');
- $data['string']= 'Press enquiries: press@example-domain.com or call 1-800-1234. General inquiries: info@example-domain.com.';
- $dwoo->output($tpl, $data);
- } catch (Exception $e) {
- echo "Error: " . $e->getMessage();
- }
- ?>
這個例子的過濾器中,作用是自動把模版合成輸出后的內(nèi)容中的含有的郵件地址自動加上mailto:的郵件鏈接。結(jié)果如下輸出:
同樣,也可以這樣寫:
- <?php
- class Dwoo_Filter_activate_mailto_links extends Dwoo_Filter
- {
- public function process($str)
- {
- return preg_replace('/([a-zA-Z0-9]+@[a-zA-Z0-9._-]+\.[a-zA-Z]+)/', '<a href="mailto:$1">$1</a>', $str);
- }
- }
- ?>
把該文件保存在dwoo下的plugins目錄中,同樣DWOO會自動加載。
#p#
五、DWOO中的緩存
Dwoo中已經(jīng)內(nèi)置了很好的緩存功能,大大提高了效率,下面講解使用dwoo緩存的步驟:
1. 在Dwoo_Template_File的構(gòu)造函數(shù)中,設(shè)定cache的名稱和緩存時間。
2. 在isCached()方法中,編寫相關(guān)的模版生成代碼,并且當(dāng)緩存存在的時候,直接返回緩存中的頁面。
下面舉一個搜索Twitter中信息的例子來說明如何使用緩存:
- <html>
- <head>
- <style type="text/css">...
- div.outer {...}{
- border-bottom: dashed orange 1px;
- padding: 4px;
- clear: both;
- height: 50px;
- }
- div.img {...}{
- float:left;
- padding-right: 2px;
- }
- span.attrib {...}{
- font-style: italic;
- }
- </style>
- </head>
- <body>
- <h2>{$title}</h2>
- {loop $records}
- <div class="outer">
- <div class="img"><img width=48" height="48" src="{$image}" /></div>
- <div>{$tweet} <br/> <span class="attrib">By <a href="{$uri}">{$owner}</a> on {$time}</span></div>
- </div>
- {/loop}
- </body>
- </html>
上面的模版是循環(huán)輸出在Twitter中檢索輸出的微博內(nèi)容。接下來看處理模版的PHP程序,如下:
- <?php
- include 'dwooAutoload.php';
- $dwoo = new Dwoo();
- $tpl = new Dwoo_Template_File('tmpl/tweets.tpl', 120, 'id_g75430i472j');
- //檢查緩存中是否已經(jīng)存在該文件,存在的話,從緩存中顯示
- if ($dwoo->isCached($tpl)) {
- $dwoo->output($tpl, array());
- echo '(cached output)';
- } else {
- //緩存中不存在,直接搜索twitter
- $result = simplexml_load_file('http://search.twitter.com/search.atom?q=pasta&lang=en');
- $records = array();
- foreach ($result->entry as $entry) {
- $item['image'] = (string)$entry->link[1]['href'];
- $item['owner'] = (string)$entry->author->name;
- $item['uri'] = (string)$entry->author->uri;
- $item['tweet'] = (string)$entry->content;
- $item['time'] = date('d M Y, h:i', strtotime($entry->published));
- $records[] = $item;
- }
- $data = new Dwoo_Data();
- $data->assign('records', $records);
- $data->assign('title', $result->title);
- $dwoo->output($tpl, $data);
- }
上面的PHP代碼中,首先是用isCached()方法,判斷緩存中是否有該文件,如果有的話則直接讀取緩存中已經(jīng)合成好的頁面文件顯示給用戶,否則的話調(diào)用twitter的Atom公開API接口去查詢關(guān)鍵字pasta,再輸出到頁面。輸出結(jié)果如下圖:
同時注意,$tpl = new Dwoo_Template_File('tmpl/tweets.tpl', 120, 'id_g75430i472j');中,第2個參數(shù)是緩存的過期時間,為120秒,第3個參數(shù)是緩存的名稱,而且該名稱在應(yīng)用中必須是唯一的。
【編輯推薦】