菜鳥學(xué)堂:
第一個目的是談?wù)摰米疃嗟哪康模O(shè)想的情形是:一組程序員編寫用于生成頁面內(nèi)容的php腳本,同時另一組設(shè)計(jì)人員設(shè)計(jì)html和圖形以控制頁面的最終外觀。分離功能和布局的基本思想就是使得這兩組人能夠各自編寫和使用獨(dú)立的一組文件:程序員只需關(guān)心那些只包含php代碼的文件,無需關(guān)心頁面的外觀;而頁面設(shè)計(jì)人員可以用自己最熟悉的可視化編輯器設(shè)計(jì)頁面布局,無需擔(dān)心破壞任何嵌入到頁面的php代碼。
如果你曾經(jīng)看過幾個關(guān)于php模板的教程,那么你應(yīng)該已經(jīng)明白模板的工作機(jī)制。考慮一個簡單的頁面局部:頁面的上方是頁頭,左邊是導(dǎo)航條,其余部分是內(nèi)容區(qū)域。
可以看出頁面如何由模板構(gòu)造而成:main模板控制著整個頁面的布局;header模板和leftnav模板控制著頁面的公共元素。花括號“{}”里面的標(biāo)識符是內(nèi)容占位符。使用模板最主要的好處在于界面設(shè)計(jì)者能夠按照自己的意愿編輯這些文件,比如設(shè)置字體、修改顏色和圖形,或者完全地改變頁面的布局。界面設(shè)計(jì)者可以用任何普通html編輯器或者可視化工具編輯這些頁面,因?yàn)檫@些文件都只包含html代碼,沒有任何php代碼。
php代碼全部保存到單獨(dú)的文件中,這個文件也就是由頁面url實(shí)際調(diào)用的文件。web服務(wù)器通過php引擎解析該文件,然后把結(jié)果返回給瀏覽器。一般地,php代碼總是動態(tài)地生成頁面內(nèi)容,比如查詢數(shù)據(jù)庫或者執(zhí)行某種計(jì)算等。下面是一個例子:
// 此處的php代碼設(shè)置$content使其包含合適的頁面內(nèi)容$tpl->assign('content', $content); $tpl->parse('header', 'header'); $tpl->parse('leftnav', 'leftnav'); $tpl->parse('main', 'main'); $tpl->fastprint('main'); ?>
這里我們使用的是流行的fasttemplate模板類,但其基本思路對于其他許多模板類來說都一樣。首先你實(shí)例化一個類,告訴它到哪里去尋找模板文件以及哪一個模板文件與頁面的哪部分對應(yīng);接下來是生成頁面內(nèi)容,把結(jié)果賦予內(nèi)容的標(biāo)識符;然后,依次解析各個模板文件,模板類將執(zhí)行必要的替換操作;最后把解析結(jié)果輸出到瀏覽器。
這個文件完全由php代碼構(gòu)成,不包含任何html代碼,這是它最大的優(yōu)點(diǎn)。現(xiàn)在,php程序員可以集中精力編寫生成頁面內(nèi)容的代碼,而不必為了如何生成html去正確地格式化最終頁面而擔(dān)心。
很容易看出采用模板還有第二個好處。如上例所示,頁面左邊的導(dǎo)航條單獨(dú)保存為一個文件,我們只需編輯這一個模板文件就可以改變網(wǎng)站所有頁面左邊的導(dǎo)航條。
避免頁面元素重復(fù)
“這確實(shí)不錯”,你也許會想,“我的網(wǎng)站主要就是由大量的靜態(tài)頁面構(gòu)成。現(xiàn)在我可以從所有頁面中刪除它們的公共部分,要更新這些公共部分實(shí)在太麻煩了。以后我就可以用模板制作出很容易維護(hù)的統(tǒng)一頁面布局。”但事情并非這么簡單,“大量的靜態(tài)頁面”道出了問題的所在。
請考慮上面的例子。這個例子實(shí)際上只有一個example.php頁面,它之所以能夠生成整個網(wǎng)站的所有頁面,是因?yàn)樗昧藆rl中的查詢字符串從數(shù)據(jù)庫之類的信息源動態(tài)地構(gòu)造出頁面。
我們之中的大多數(shù)人所運(yùn)行的網(wǎng)站并不一定都有數(shù)據(jù)庫支持。我們的網(wǎng)站大多數(shù)由靜態(tài)頁面構(gòu)成,然后用php在這里、那里加上一些動態(tài)功能,比如搜索引擎、反饋表單等。那么,如何在這種網(wǎng)站上應(yīng)用模板呢?
最簡單的方法是為每一個頁面復(fù)制一份php文件,然后在每一個頁面中把php代碼里代表內(nèi)容的變量設(shè)置成合適的頁面內(nèi)容。例如,假設(shè)有三個頁面,它們分別是主頁(home)、關(guān)于(about)和產(chǎn)品(product),我們可以用三個文件分別生成它們。這三個文件的內(nèi)容都類如:
<p>希望你能夠喜歡本網(wǎng)站</p>"; $tpl->assign('content', $content); $tpl->parse('header', 'header'); $tpl->parse('leftnav', 'leftnav'); $tpl->parse('main', 'main'); $tpl->fastprint('main'); ?>
顯然,這種方法有三個問題:我們必須為每一個頁面復(fù)制這些復(fù)雜的、牽涉到模板的php代碼,這與重復(fù)公共頁面元素一樣使得頁面難以維護(hù);現(xiàn)在文件又混合了html和php代碼;為內(nèi)容變量賦值將變得非常困難,因?yàn)槲覀儽仨毺幚砗么罅康奶厥庾址?
解決這個問題的關(guān)鍵就在于分離php代碼和html內(nèi)容,雖然我們不能從文件中刪除所有的html內(nèi)容,但可以移出絕大多數(shù)php代碼。
靜態(tài)網(wǎng)站的模板框架:
ob_end_clean(); $tpl->assign('content', $content); $tpl->parse('header', 'header'); $tpl->parse('leftnav', 'leftnav'); $tpl->parse('main', 'main'); $tpl->fastprint('main'); } ?>
agestart函數(shù)首先創(chuàng)建并設(shè)置了一個模板實(shí)例,然后啟用輸出緩存。此后,所有來自頁面本身的html內(nèi)容都將進(jìn)入緩存。pagefinish函數(shù)取出緩存中的內(nèi)容,然后在模板對象中指定這些內(nèi)容,最后解析模板并輸出完成后的頁面。
這就是整個模板框架全部的工作過程了。首先編寫包含了網(wǎng)站各個頁面公共元素的模板,然后從所有頁面中刪除全部公共的頁面布局代碼,代之以三行永遠(yuǎn)無需改動的php代碼;再把fasttemplate類文件和prepend.php加入到包含路徑,這樣你就得到了一個頁面布局可以集中控制的網(wǎng)站,它有著更好的可靠性和可維護(hù)性,而且網(wǎng)站級的大范圍修改也變得相當(dāng)容易。