我(wǒ)(wǒ)們先回顧一(yī)些基本的概念。
一(yī),PHP腳本與動态頁面。
PHP腳本是一(yī)種服務器端腳本程序,可通過嵌入等方法與HTML文件混合,也可以類,函數封裝等形式,以模闆的方式對用戶請求進行處理。無論以何種方式,它的基本原理是這樣的。由客戶端提出請求,請求某一(yī)頁面----->WEB服務器引入指定相應腳本進行處理----->腳本被載入服務器----->由服務器指定的PHP解析器對腳本進行解析形成HTML語言形式---->将解析後的HTML語句以包的方式傳回給浏覽器。由此不難看出,在頁面發送到浏覽器後,PHP就不存在了,已被轉化解析爲HTML語句。客戶請求爲一(yī)動态文件,事實上并沒有真正的文件存在在那裏,是PHP解析而成相對應的頁面,然後發送回浏覽器。這種頁面處理方式被稱爲“動态頁面”。
二,靜态頁面。
靜态頁面是指在服務器端确實存在的僅含HTML以及JS,CSS等客戶端運行腳本的頁面。它的處理方式是。由客戶端提出請求,請求某一(yī)頁面---->WEB服務器确認并載入某一(yī)頁面---->WEB服務器将該頁面以包的形式傳遞回浏覽器。由這一(yī)過程,我(wǒ)(wǒ)們對比一(yī)下(xià)動态頁面,即可方現。動态頁面需由WEB服務器的PHP解析器進行解析,而且通常還需連接數據庫,進行數據庫存取操作,然後才能形成HTML語言信息包;而靜态頁面,無須解析,無須連接數據庫,直接發送,可大(dà)大(dà)減輕服務器壓力,提高服務器負載能力,大(dà)幅提供頁面打開(kāi)速度和網站整體(tǐ)打開(kāi)速度。但其缺點是,不能動态地對請求進行處理,服務器上必須确實存在該文件。
三,模闆及模闆解析。
模闆即尚未填充内容html文件。例如:
temp.html
Code:
<HTML>
<TITLE>{ title }</TITLE>
<BODY>
this is a { file } file's templets
</BODY>
</HTML>
PHP處理:
templetest.php
Code:
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,
author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{ file }",$file,$content);
$content .= str_replace ("{ title }",$title,$content);
echo $content;
?>
模闆解析處理,即将經PHP腳本解析處理後得出的結果填充(content)進模闆的處理過程。通常借助于模闆類。目前較流行的模闆解析類有phplib,smarty,fastsmarty等等。模闆解析處理的原理通常爲替換。也有些程序員(yuán)習慣将判斷,循環等處理放(fàng)進模闆文件中(zhōng),用解析類處理,典型應用爲block概念,簡單來說即爲一(yī)個循環處理。由PHP腳本指定循環次數,如何循環代入等,再由模闆解析類具體(tǐ)實施這些操作。
好了,對比過靜态頁面與動态頁面各自的優劣,現在我(wǒ)(wǒ)們就來說說,如何用PHP生(shēng)成靜态文件。
PHP生(shēng)成靜态頁面并不是指PHP的動态解析,輸出HTML頁面,而是指用PHP創建HTML頁面。同時因爲HTML的不可寫性,我(wǒ)(wǒ)們創建的HTML若有修改,則需删掉重新生(shēng)成即可。(當然你也可以選擇用正則進行修改,但個人認爲那樣做倒不如删掉重新生(shēng)成來得快捷,有些得不償失。)
言歸正傳。用過PHP文件操作函數的PHP FANS知(zhī)道,PHP中(zhōng)有一(yī)個文件操作函數fopen,即打開(kāi)文件。若文件不存在,則嘗試創建。這即是PHP可以用來創建HTML文件的理論基礎。隻要用來存放(fàng)HTML文件的文件夾有寫權限(即權限定義0777),即可創建文件。(針對UNIX系統而言,Win系統無須考慮。)仍以上例爲例,若我(wǒ)(wǒ)們修改最後一(yī)句,并指定在test目錄下(xià)生(shēng)成一(yī)個名爲test.html的靜态文件:
Code:
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,
author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{ file }",$file,$content);
$content .= str_replace ("{ title }",$title,$content);
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
實際應用中(zhōng)常見問題解決方案參考:
一(yī),文章列表問題:
在數據庫中(zhōng)創建字段,記錄文件名,每生(shēng)成一(yī)個文件,将自動生(shēng)成的文件名存入數據庫,對于推薦文章,隻需指向存放(fàng)靜态文件的指定文件夾中(zhōng)的該頁面即可。利用PHP操作處理文章列表,存爲字符串,生(shēng)成頁面時替換此字符串即可。如,在頁面中(zhōng)放(fàng)置文章列表的表格加入标記{ articletable },而在PHP處理文件中(zhōng):
Code:
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,
author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{ file }",$file,$content);
$content .= str_replace ("{ title }",$title,$content);
// 生(shēng)成列表開(kāi)始
$list = '';
$sql = "select id,title,filename from article";
$query = mysql_query ($sql);
while ($result = mysql_fetch_array ($query)){
$list .= ''.$result['title'].'
';
}
$content .= str_replace ("{ articletable }",$list,$content);
//生(shēng)成列表結束
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
二,分(fēn)頁問題。
如我(wǒ)(wǒ)們指定分(fēn)頁時,每頁20篇。某子頻(pín)道列表内文章經數據庫查詢爲45條,則,首先我(wǒ)(wǒ)們通過查詢得到如下(xià)參數:1,總頁數;2,每頁篇數。第二步,for ($i = 0; $i < allpages; $i++),頁面元素獲取,分(fēn)析,文章生(shēng)成,都在此循環中(zhōng)執行。不同的是,die ("創建文件".$filename."成功!";這句去(qù)掉,放(fàng)到循環後的顯示,因爲該語句将中(zhōng)止程序執行。例:
Code:
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$onepage = '20';
$sql = "select id from article where channel='$channelid'";
$query = mysql_query ($sql);
$num = mysql_num_rows ($query);
$allpages = ceil ($num / $onepage);
for ($i = 0;$i<$allpages; $i++){
if ($i == 0){
$indexpath = "index.html";
} else {
$indexpath = "index_".$i."html";
}
$start = $i * $onepage;
$list = '';
$sql_for_page = "select name,filename,title from article where channel='$channelid' limit $start,$onepage";
$query_for_page = mysql_query ($sql_for_page);
while ($result = $query_for_page){
$list .= ''.$title.'
';
}
$content = str_replace ("{ articletable }",$list,$content);
if (is_file ($indexpath)){
@unlink ($indexpath); //若文件已存在,則删除
}
$handle = fopen ($indexpath,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($indexpath)){
echo "文件:".$indexpath."不可寫,請檢查其屬性後重試!"; //修改爲echo
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
echo "生(shēng)成文件".$indexpath."失敗!"; //修改爲echo
}
fclose ($handle); //關閉指針
}
fclose ($fp);
die ("生(shēng)成分(fēn)頁文件完成,如生(shēng)成不完全,請檢查文件權限系統後重新生(shēng)成!");
?>
大(dà)緻思路如此,其中(zhōng)如其它數據生(shēng)成,數據輸入輸出檢查,分(fēn)頁内容指向等可酌情在頁面中(zhōng)加入。
在實際文章系統處理過程當中(zhōng),還有許多問題有待考慮,與動态頁面不同之處,需注意的地方還有很多。但大(dà)緻思路即是如此,其它方面可舉一(yī)反三而得。
用PHP制作靜态網站的模闆框架
----------------------------------------------------
模闆能夠改善網站的結構。本文闡述如何通過PHP 4的一(yī)個新功能和模闆類,在由大(dà)量靜态HTML頁面構成的網站中(zhōng)巧妙地運用模闆控制頁面布局。
提綱:
===================================
分(fēn)離(lí)功能和布局
避免頁面元素重複
靜态網站的模闆框架
===================================
分(fēn)離(lí)功能和布局
首先我(wǒ)(wǒ)們來看看應用模闆的兩個主要目的:
分(fēn)離(lí)功能(PHP)和布局(HTML)
避免頁面元素重複
第一(yī)個目的是談論得最多的目的,它設想的情形是:一(yī)組程序員(yuán)編寫用于生(shēng)成頁面内容的PHP腳本,同時另一(yī)組設計人員(yuán)設計HTML和圖形以控制頁面的最終外(wài)觀。分(fēn)離(lí)功能和布局的基本思想就是使得這兩組人能夠各自編寫和使用獨立的一(yī)組文件:程序員(yuán)隻需關心那些隻包含PHP代碼的文件,無需關心頁面的外(wài)觀;而頁面設計人員(yuán)可以用自己最熟悉的可視化編輯器設計頁面布局,無需擔心破壞任何嵌入到頁面的PHP代碼。
如果你曾經看過幾個關于PHP模闆的教程,那麽你應該已經明白(bái)模闆的工(gōng)作機制。考慮一(yī)個簡單的頁面局部:頁面的上方是頁頭,左邊是導航條,其餘部分(fēn)是内容區域。這種網站可以擁有如下(xià)模闆文件:
<!-- main.htm -->
<html>
<head><title>模闆示例</title></head>
<body>
<table><tr><td>{HEADER}</td></tr>
<tr><td>{LEFTNAV}</td><td>{CONTENT}</td></tr>
</table>
</body></html>
<!-- header.htm -->
<img src="http://www.abcdown.net/InfoView/sitelogo.jpg">
<!-- leftnav.htm -->
<br><a href="foo">Foo</a>
<br><a href="bar">Bar</a>
可以看出頁面如何由這些模闆構造而成:main模闆控制着整個頁面的布局;header模闆和leftnav模闆控制着頁面的公共元素。花括号“{}”裏面的标識符是内容占位符。使用模闆最主要的好處在于界面設計者能夠按照自己的意願編輯這些文件,比如設置字體(tǐ)、修改顔色和圖形,或者完全地改變頁面的布局。界面設計者可以用任何普通HTML編輯器或者可視化工(gōng)具編輯這些頁面,因爲這些文件都隻包含HTML代碼,沒有任何PHP代碼。
PHP代碼全部保存到單獨的文件中(zhōng),這個文件也就是由頁面URL實際調用的文件。Web服務器通過PHP引擎解析該文件,然後把結果返回給浏覽器。一(yī)般地,PHP代碼總是動态地生(shēng)成頁面内容,比如查詢數據庫或者執行某種計算等。下(xià)面是一(yī)個例子:
<?php
// example.php
require('class.FastTemplate.php');
$tpl = new FastTemplate('.');
$tpl->define( array( 'main' => 'main.htm',
'header' => 'header.htm',
'leftnav' => 'leftnav.htm' ) );
// 此處的PHP代碼設置$content使其包含合适的頁面内容
$tpl->assign('CONTENT', $content);
$tpl->parse('HEADER', 'header');
$tpl->parse('LEFTNAV', 'leftnav');
$tpl->parse('MAIN', 'main');
$tpl->FastPrint('MAIN');
?>
這裏我(wǒ)(wǒ)們使用的是流行的FastTemplate模闆類,但其基本思路對于其他許多模闆類來說都一(yī)樣。首先你實例化一(yī)個類,告訴它到哪裏去(qù)尋找模闆文件以及哪一(yī)個模闆文件與頁面的哪部分(fēn)對應;接下(xià)來是生(shēng)成頁面内容,把結果賦予内容的标識符;然後,依次解析各個模闆文件,模闆類将執行必要的替換操作;最後把解析結果輸出到浏覽器。
這個文件完全由PHP代碼構成,不包含任何HTML代碼,這是它最大(dà)的優點。現在,PHP程序員(yuán)可以集中(zhōng)精力編寫生(shēng)成頁面内容的代碼,而不必爲了如何生(shēng)成HTML去(qù)正确地格式化最終頁面而擔心。
你可以使用這種方法和上面的文件構造出一(yī)個完整的網站。如果PHP代碼是以URL中(zhōng)的查詢字符串爲基礎生(shēng)成頁面内容,例如http://www.foo.com/example.php?article=099,你可以據此構造出一(yī)個完整的雜(zá)志(zhì)網站。
很容易看出采用模闆還有第二個好處。如上例所示,頁面左邊的導航條單獨保存爲一(yī)個文件,我(wǒ)(wǒ)們隻需編輯這一(yī)個模闆文件就可以改變網站所有頁面左邊的導航條。
避免頁面元素重複
“這确實不錯”,你也許會想,“我(wǒ)(wǒ)的網站主要就是由大(dà)量的靜态頁面構成。現在我(wǒ)(wǒ)可以從所有頁面中(zhōng)删除它們的公共部分(fēn),要更新這些公共部分(fēn)實在太麻煩了。以後我(wǒ)(wǒ)就可以用模闆制作出很容易維護的統一(yī)頁面布局。”但事情并非這麽簡單,“大(dà)量的靜态頁面”道出了問題的所在。
請考慮上面的例子。這個例子實際上隻有一(yī)個example.php頁面,它之所以能夠生(shēng)成整個網站的所有頁面,是因爲它利用了URL中(zhōng)的查詢字符串從數據庫之類的信息源動态地構造出頁面。
我(wǒ)(wǒ)們之中(zhōng)的大(dà)多數人所運行的網站并不一(yī)定都有數據庫支持。我(wǒ)(wǒ)們的網站大(dà)多數由靜态頁面構成,然後用PHP在這裏、那裏加上一(yī)些動态功能,比如搜索引擎、反饋表單等。那麽,如何在這種網站上應用模闆呢?
最簡單的方法是爲每一(yī)個頁面複制一(yī)份PHP文件,然後在每一(yī)個頁面中(zhōng)把PHP代碼裏代表内容的變量設置成合适的頁面内容。例如,假設有三個頁面,它們分(fēn)别是主頁(home)、關于(about)和産品(product),我(wǒ)(wǒ)們可以用三個文件分(fēn)别生(shēng)成它們。這三個文件的内容都類如:
<?php
// home.php
require('class.FastTemplate.php');
$tpl = new FastTemplate('.');
$tpl->define( array( 'main' => 'main.htm',
'header' => 'header.htm',
'leftnav' => 'leftnav.htm' ) );
$content = "<p>歡迎訪問</p>
<img src=\"demo.jpg\">
<p>希望你能夠喜歡本網站</p>";
$tpl->assign('CONTENT', $content);
$tpl->parse('HEADER', 'header');
$tpl->parse('LEFTNAV', 'leftnav');
$tpl->parse('MAIN', 'main');
$tpl->FastPrint('MAIN');
?>
顯然,這種方法有三個問題:我(wǒ)(wǒ)們必須爲每一(yī)個頁面複制這些複雜(zá)的、牽涉到模闆的PHP代碼,這與重複公共頁面元素一(yī)樣使得頁面難以維護;現在文件又(yòu)混合了HTML和PHP代碼;爲内容變量賦值将變得非常困難,因爲我(wǒ)(wǒ)們必須處理好大(dà)量的特殊字符。
解決這個問題的關鍵就在于分(fēn)離(lí)PHP代碼和HTML内容,雖然我(wǒ)(wǒ)們不能從文件中(zhōng)删除所有的HTML内容,但可以移出絕大(dà)多數PHP代碼。
靜态網站的模闆框架
首先,我(wǒ)(wǒ)們象前面一(yī)樣爲所有的頁面公用元素以及頁面整體(tǐ)布局編寫模闆文件;然後從所有的頁面删除公共部分(fēn),隻留下(xià)頁面内容;接下(xià)來再在每個頁面中(zhōng)加上三行PHP代碼,如下(xià)所示:
<?php
<!-- home.php -->
<?php require('prepend.php'); ?>
<?php pageStart('Home'); ?>
<h1>你好</h1>
<p>歡迎訪問</p>
<img src="http://www.abcdown.net/InfoView/demo.jpg">
<p>希望你能夠喜歡本網站</p>
<?php pageFinish(); ?>
?>
這種方法基本上解決了前面提到的各種問題。現在文件裏隻有三行PHP代碼,而且沒有任何一(yī)行代碼直接涉及到模闆,因此要改動這些代碼的可能性極小(xiǎo)。此外(wài),由于HTML内容位于PHP标記之外(wài),所以也不存在特殊字符的處理問題。我(wǒ)(wǒ)們可以很容易地将這三行PHP代碼加入到所有靜态HTML頁面中(zhōng)。
require函數引入了一(yī)個PHP文件,這個文件包含了所有必需的與模闆相關的PHP代碼。其中(zhōng)pageStart函數設置模闆對象以及頁面标題,pageFinish函數解析模闆然後生(shēng)成結果發送給浏覽器。
這是如何實現的呢?爲什麽在調用pageFinish函數之前文件中(zhōng)的HTML不會發送給浏覽器?答案就在于PHP 4的一(yī)個新功能,這個功能允許把輸出到浏覽器的内容截獲到緩沖區之中(zhōng)。讓我(wǒ)(wǒ)們來看看prepend.php的具體(tǐ)代碼:
<?php
require('class.FastTemplate.php');
function pageStart($title = '') {
GLOBAL $tpl;
$tpl = new FastTemplate('.');
$tpl->define( array( 'main' => 'main.htm',
'header' => 'header.htm',
'leftnav'=> 'leftnav.htm' ) );
$tpl->assign('TITLE', $title);
ob_start();
}
function pageFinish() {
GLOBAL $tpl;
$content = ob_get_contents();
ob_end_clean();
$tpl->assign('CONTENT', $content);
$tpl->parse('HEADER', 'header');
$tpl->parse('LEFTNAV', 'leftnav');
$tpl->parse('MAIN', 'main');
$tpl->FastPrint('MAIN');
}
?>
pageStart函數首先創建并設置了一(yī)個模闆實例,然後啓用輸出緩存。此後,所有來自頁面本身的HTML内容都将進入緩存。pageFinish函數取出緩存中(zhōng)的内容,然後在模闆對象中(zhōng)指定這些内容,最後解析模闆并輸出完成後的頁面。
這就是整個模闆框架全部的工(gōng)作過程了。首先編寫包含了網站各個頁面公共元素的模闆,然後從所有頁面中(zhōng)删除全部公共的頁面布局代碼,代之以三行永遠無需改動的PHP代碼;再把FastTemplate類文件和prepend.php加入到包含路徑,這樣你就得到了一(yī)個頁面布局可以集中(zhōng)控制的網站,它有着更好的可靠性和可維護性,而且網站級的大(dà)範圍修改也變得相當容易。
本文下(xià)載包包含了一(yī)個可運行的示例網站,它的代碼注釋要比前面的代碼注釋更詳細一(yī)些。FastTemplate類可以在http://www.thewebmasters.net/找到,最新的版本号是1.1.0,那裏還有一(yī)個用于保證該類在PHP 4中(zhōng)正确運行的小(xiǎo)補丁。本文下(xià)載代碼中(zhōng)的類已經經過該補丁的修正。
PHP簡易生(shēng)成靜态頁面
<?php
/*
* 文件名:index.php
*/
require "conn.php";
$query = "select * from news order by datetime desc";
$result = mysql_query($query);
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
<title>NEWS</title>
</head>
<body>
<table width="500" border="1" align="center">
<tr>
<td>标題</td>
<td width="200">發布時間</td>
</tr>
<?
while($re = mysql_fetch_array($result)){
?>
<tr>
<td><a href="<?= $re["newsid"].".html"?>"><?= $re["title"]?></a></td>
<td><?= $re["datetime"]?></td>
</tr>
<?
}
?>
<tr>
<td> </td>
<td><a href="addnews.php">添加新聞</a></td>
</tr>
</table>
</body>
</html>
--------------------------------------------------------------------------
<?php
/*
文件名:AddNews.php
簡易動态添加生(shēng)成靜态新聞頁面
#
# 表的結構 `news`
#
CREATE TABLE `news` (
`newsid` int(11) NOT NULL auto_increment,
`title` varchar(100) NOT NULL default '',
`content` text NOT NULL,
`datetime` datetime NOT NULL default '0000-00-00 00:00:00',
KEY `newsid` (`newsid`)
) TYPE=MyISAM AUTO_INCREMENT=11 ;
*/
if(isset($_POST["title"])){
$title = $_POST["title"];
$content = $_POST["content"];
//定義模版文件的内容,可用其它方法
$filecontent = '<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
<title>{title}</title>
</head>
<body>
<table width="500" border="1" align="center">
<tr>
<td align="center"><strong>{title}</strong></td>
</tr>
<tr>
<td>{content}</td>
</tr>
<tr>
<td align="right">{datetime}</td>
</tr>
</table>
</body>
</html>
';
$datetime = date("Y-m-d H:i:s");
$query = "insert into news values('','".$title."','".$content."','".$datetime."')";
require "conn.php";//連接數據庫
$result = mysql_query($query) or die(mysql_error());
if($result){
$id = mysql_insert_id();
$filename = $id.".html";
if($fp = fopen($filename, "w")){//新建文件,成功後添加内容
$filecontent = str_replace("{title}", $title, $filecontent);
$filecontent = str_replace("{content}", $content, $filecontent);
$filecontent = str_replace("{datetime}", $datetime, $filecontent);
if(!fwrite($fp, $filecontent)){//把内容寫入文件
$query = "delete from news where newsid=".$id;
$result = mysql_query($query) or die(mysql_error());
fclose($fp);
unlink($filename);
echo "<script>alert('Add news failed!');location.href='index.php';</script>";
exit;
}else {
echo "<script>alert('Add news successed!');location.href='index.php';</script>";
}
}
}
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
<title>添加</title>
</head>
<body>
<form name="form1" method="post" action="">
<table width="500" border="1" align="center">
<tr>
<td>标題</td>
<td><input name="title" type="text" id="title" size="40"></td>
</tr>
<tr>
<td>内容</td>
<td><textarea name="content" cols="45" rows="6" id="content"></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="Submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
PHP生(shēng)成靜态頁面詳解
應用實例:
http://xjtusky.net/down
說明:有一(yī)部分(fēn)功能還沒有完全做好,修改中(zhōng),有興趣的朋友可以看看下(xià)面這篇文章,看
完了一(yī)定要說好!生(shēng)成頁面的速度快的~~~呵呵。下(xià)面文章中(zhōng)一(yī)些地方請自行修改!
PHP生(shēng)成靜态頁面詳解
http://xjtusky.net/article/htmld ... /article_594_1.html
看到很多朋友在各個地方發帖問PHP生(shēng)成靜态文章系統的方法,以前曾做過這樣一(yī)個系
統,遂談些看法,以供各位參考。好了,我(wǒ)(wǒ)們先回顧一(yī)些基本的概念。
一(yī),PHP腳本與動态頁面。
PHP腳本是一(yī)種服務器端腳本程序,可通過嵌入等方法與HTML文件混合,也可以類,函
數封裝等形式,以模闆的方式對用戶請求進行處理。無論以何種方式,它的基本原理是這
樣的。由客戶端提出請求,請求某一(yī)頁面----->WEB服務器引入指定相應腳本進行處理
----->腳本被載入服務器----->由服務器指定的PHP解析器對腳本進行解析形成H
TML語言形式---->将解析後的HTML語句以包的方式傳回給浏覽器。由此不難看出,在
頁面發送到浏覽器後,PHP就不存在了,已被轉化解析爲HTML語句。客戶請求爲一(yī)動态文件
,事實上并沒有真正的文件存在在那裏,是PHP解析而成相對應的頁面,然後發送回浏覽器
。這種頁面處理方式被稱爲“動态頁面”。
二,靜态頁面。
靜态頁面是指在服務器端确實存在的僅含HTML以及JS,CSS等客戶端運行腳本的頁面。
它的處理方式是。由客戶端提出請求,請求某一(yī)頁面---->WEB服務器确認并載入某一(yī)
頁面---->WEB服務器将該頁面以包的形式傳遞回浏覽器。由這一(yī)過程,我(wǒ)(wǒ)們對比一(yī)下(xià)
動态頁面,即可方現。動态頁面需由WEB服務器的PHP解析器進行解析,而且通常還需連接
數據庫,進行數據庫存取操作,然後才能形成HTML語言信息包;而靜态頁面,無須解析,
無須連接數據庫,直接發送,可大(dà)大(dà)減輕服務器壓力,提高服務器負載能力,大(dà)幅提供頁
面打開(kāi)速度和網站整體(tǐ)打開(kāi)速度。但其缺點是,不能動态地對請求進行處理,服務器上必
須确實存在該文件。
三,模闆及模闆解析。
模闆即尚未填充内容html文件。例如:
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
temp.html
<HTML>
<TITLE>{title}</TITLE>
<BODY>
this is a {file} file's templets
</BODY>
</HTML>
PHP處理:
templetest.php
<?php
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,<br>author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{file}",$file,$content);
$content .= str_replace ("{title}",$title,$content);
echo $content;
?>
模闆解析處理,即将經PHP腳本解析處理後得出的結果填充(content)進模闆的處理過
程。通常借助于模闆類。目前較流行的模闆解析類有phplib,smarty,fastsmarty等等。
模闆解析處理的原理通常爲替換。也有些程序員(yuán)習慣将判斷,循環等處理放(fàng)進模闆文件中(zhōng)
,用解析類處理,典型應用爲block概念,簡單來說即爲一(yī)個循環處理。由PHP腳本指定循
環次數,如何循環代入等,再由模闆解析類具體(tǐ)實施這些操作。
好了,對比過靜态頁面與動态頁面各自的優劣,現在我(wǒ)(wǒ)們就來說說,如何用PHP生(shēng)成靜
态文件。
PHP生(shēng)成靜态頁面并不是指PHP的動态解析,輸出HTML頁面,而是指用PHP創建HTML頁面
。同時因爲HTML的不可寫性,我(wǒ)(wǒ)們創建的HTML若有修改,則需删掉重新生(shēng)成即可。(當然你
也可以選擇用正則進行修改,但個人認爲那樣做倒不如删掉重新生(shēng)成來得快捷,有些得不
償失。)
言歸正傳。用過PHP文件操作函數的PHP FANS知(zhī)道,PHP中(zhōng)有一(yī)個文件操作函數fopen,
即打開(kāi)文件。若文件不存在,則嘗試創建。這即是PHP可以用來創建HTML文件的理論基礎。
隻要用來存放(fàng)HTML文件的文件夾有寫權限(即權限定義0777),即可創建文件。(針對UNIX
系統而言,Win系統無須考慮。)仍以上例爲例,若我(wǒ)(wǒ)們修改最後一(yī)句,并指定在test目錄
下(xià)生(shēng)成一(yī)個名爲test.html的靜态文件:
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
<?php
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,<br>author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{file}",$file,$content);
$content .= str_replace ("{title}",$title,$content);
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
實際應用中(zhōng)常見問題解決方案參考:
一(yī),文章列表問題:
在數據庫中(zhōng)創建字段,記錄文件名,每生(shēng)成一(yī)個文件,将自動生(shēng)成的文件名存入數據
庫,對于推薦文章,隻需指向存放(fàng)靜态文件的指定文件夾中(zhōng)的該頁面即可。利用PHP操作處
理文章列表,存爲字符串,生(shēng)成頁面時替換此字符串即可。如,在頁面中(zhōng)放(fàng)置文章列表的
表格加入标記{articletable},而在PHP處理文件中(zhōng):
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
<?php
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,<br>author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{file}",$file,$content);
$content .= str_replace ("{title}",$title,$content);
// 生(shēng)成列表開(kāi)始
$list = '';
$sql = "select id,title,filename from article";
$query = mysql_query ($sql);
while ($result = mysql_fetch_array ($query)){
$list .= '<a href='.$root.$result['filename'].' target=_blank>'.$result[
'title'].'</a><br>';
}
$content .= str_replace ("{articletable}",$list,$content);
//生(shēng)成列表結束
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
二,分(fēn)頁問題。
如我(wǒ)(wǒ)們指定分(fēn)頁時,每頁20篇。某子頻(pín)道列表内文章經數據庫查詢爲45條,則,首先
我(wǒ)(wǒ)們通過查詢得到如下(xià)參數:1,總頁數;2,每頁篇數。第二步,for ($i = 0; $i < al
lpages; $i++),頁面元素獲取,分(fēn)析,文章生(shēng)成,都在此循環中(zhōng)執行。不同的是,die (
"創建文件".$filename."成功!";這句去(qù)掉,放(fàng)到循環後的顯示,因爲該語句将中(zhōng)止程序
執行。例:
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
<?php
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$onepage = '20';
$sql = "select id from article where channel='$channelid'";
$query = mysql_query ($sql);
$num = mysql_num_rows ($query);
$allpages = ceil ($num / $onepage);
for ($i = 0;$i<$allpages; $i++){
if ($i == 0){
$indexpath = "index.html";
} else {
$indexpath = "index_".$i."html";
}
$start = $i * $onepage;
$list = '';
$sql_for_page = "select name,filename,title from article where channel='
$channelid' limit $start,$onepage";
$query_for_page = mysql_query ($sql_for_page);
while ($result = $query_for_page){
$list .= '<a href='.$root.$result['filename'].' target=_blank>'.$titl
e.'</a><br>';
}
$content = str_replace ("{articletable}",$list,$content);
if (is_file ($indexpath)){
@unlink ($indexpath); //若文件已存在,則删除
}
$handle = fopen ($indexpath,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($indexpath)){
echo "文件:".$indexpath."不可寫,請檢查其屬性後重試!"; //修改爲echo
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
echo "生(shēng)成文件".$indexpath."失敗!"; //修改爲echo
}
fclose ($handle); //關閉指針
}
fclose ($fp);
die ("生(shēng)成分(fēn)頁文件完成,如生(shēng)成不完全,請檢查文件權限系統後重新生(shēng)成!");
?>
大(dà)緻思路如此,其中(zhōng)如其它數據生(shēng)成,數據輸入輸出檢查,分(fēn)頁内容指向等可酌情在
頁面中(zhōng)加入。
在實際文章系統處理過程當中(zhōng),還有許多問題有待考慮,與動态頁面不同之處,需注
意的地方還有很多。但大(dà)緻思路即是如此,其它方面可舉一(yī)反三而得。
一(yī),PHP腳本與動态頁面。
PHP腳本是一(yī)種服務器端腳本程序,可通過嵌入等方法與HTML文件混合,也可以類,函數封裝等形式,以模闆的方式對用戶請求進行處理。無論以何種方式,它的基本原理是這樣的。由客戶端提出請求,請求某一(yī)頁面----->WEB服務器引入指定相應腳本進行處理----->腳本被載入服務器----->由服務器指定的PHP解析器對腳本進行解析形成HTML語言形式---->将解析後的HTML語句以包的方式傳回給浏覽器。由此不難看出,在頁面發送到浏覽器後,PHP就不存在了,已被轉化解析爲HTML語句。客戶請求爲一(yī)動态文件,事實上并沒有真正的文件存在在那裏,是PHP解析而成相對應的頁面,然後發送回浏覽器。這種頁面處理方式被稱爲“動态頁面”。
二,靜态頁面。
靜态頁面是指在服務器端确實存在的僅含HTML以及JS,CSS等客戶端運行腳本的頁面。它的處理方式是。由客戶端提出請求,請求某一(yī)頁面---->WEB服務器确認并載入某一(yī)頁面---->WEB服務器将該頁面以包的形式傳遞回浏覽器。由這一(yī)過程,我(wǒ)(wǒ)們對比一(yī)下(xià)動态頁面,即可方現。動态頁面需由WEB服務器的PHP解析器進行解析,而且通常還需連接數據庫,進行數據庫存取操作,然後才能形成HTML語言信息包;而靜态頁面,無須解析,無須連接數據庫,直接發送,可大(dà)大(dà)減輕服務器壓力,提高服務器負載能力,大(dà)幅提供頁面打開(kāi)速度和網站整體(tǐ)打開(kāi)速度。但其缺點是,不能動态地對請求進行處理,服務器上必須确實存在該文件。
三,模闆及模闆解析。
模闆即尚未填充内容html文件。例如:
temp.html
Code:
<HTML>
<TITLE>{ title }</TITLE>
<BODY>
this is a { file } file's templets
</BODY>
</HTML>
PHP處理:
templetest.php
Code:
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,
author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{ file }",$file,$content);
$content .= str_replace ("{ title }",$title,$content);
echo $content;
?>
模闆解析處理,即将經PHP腳本解析處理後得出的結果填充(content)進模闆的處理過程。通常借助于模闆類。目前較流行的模闆解析類有phplib,smarty,fastsmarty等等。模闆解析處理的原理通常爲替換。也有些程序員(yuán)習慣将判斷,循環等處理放(fàng)進模闆文件中(zhōng),用解析類處理,典型應用爲block概念,簡單來說即爲一(yī)個循環處理。由PHP腳本指定循環次數,如何循環代入等,再由模闆解析類具體(tǐ)實施這些操作。
好了,對比過靜态頁面與動态頁面各自的優劣,現在我(wǒ)(wǒ)們就來說說,如何用PHP生(shēng)成靜态文件。
PHP生(shēng)成靜态頁面并不是指PHP的動态解析,輸出HTML頁面,而是指用PHP創建HTML頁面。同時因爲HTML的不可寫性,我(wǒ)(wǒ)們創建的HTML若有修改,則需删掉重新生(shēng)成即可。(當然你也可以選擇用正則進行修改,但個人認爲那樣做倒不如删掉重新生(shēng)成來得快捷,有些得不償失。)
言歸正傳。用過PHP文件操作函數的PHP FANS知(zhī)道,PHP中(zhōng)有一(yī)個文件操作函數fopen,即打開(kāi)文件。若文件不存在,則嘗試創建。這即是PHP可以用來創建HTML文件的理論基礎。隻要用來存放(fàng)HTML文件的文件夾有寫權限(即權限定義0777),即可創建文件。(針對UNIX系統而言,Win系統無須考慮。)仍以上例爲例,若我(wǒ)(wǒ)們修改最後一(yī)句,并指定在test目錄下(xià)生(shēng)成一(yī)個名爲test.html的靜态文件:
Code:
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,
author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{ file }",$file,$content);
$content .= str_replace ("{ title }",$title,$content);
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
實際應用中(zhōng)常見問題解決方案參考:
一(yī),文章列表問題:
在數據庫中(zhōng)創建字段,記錄文件名,每生(shēng)成一(yī)個文件,将自動生(shēng)成的文件名存入數據庫,對于推薦文章,隻需指向存放(fàng)靜态文件的指定文件夾中(zhōng)的該頁面即可。利用PHP操作處理文章列表,存爲字符串,生(shēng)成頁面時替換此字符串即可。如,在頁面中(zhōng)放(fàng)置文章列表的表格加入标記{ articletable },而在PHP處理文件中(zhōng):
Code:
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,
author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{ file }",$file,$content);
$content .= str_replace ("{ title }",$title,$content);
// 生(shēng)成列表開(kāi)始
$list = '';
$sql = "select id,title,filename from article";
$query = mysql_query ($sql);
while ($result = mysql_fetch_array ($query)){
$list .= ''.$result['title'].'
';
}
$content .= str_replace ("{ articletable }",$list,$content);
//生(shēng)成列表結束
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
二,分(fēn)頁問題。
如我(wǒ)(wǒ)們指定分(fēn)頁時,每頁20篇。某子頻(pín)道列表内文章經數據庫查詢爲45條,則,首先我(wǒ)(wǒ)們通過查詢得到如下(xià)參數:1,總頁數;2,每頁篇數。第二步,for ($i = 0; $i < allpages; $i++),頁面元素獲取,分(fēn)析,文章生(shēng)成,都在此循環中(zhōng)執行。不同的是,die ("創建文件".$filename."成功!";這句去(qù)掉,放(fàng)到循環後的顯示,因爲該語句将中(zhōng)止程序執行。例:
Code:
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$onepage = '20';
$sql = "select id from article where channel='$channelid'";
$query = mysql_query ($sql);
$num = mysql_num_rows ($query);
$allpages = ceil ($num / $onepage);
for ($i = 0;$i<$allpages; $i++){
if ($i == 0){
$indexpath = "index.html";
} else {
$indexpath = "index_".$i."html";
}
$start = $i * $onepage;
$list = '';
$sql_for_page = "select name,filename,title from article where channel='$channelid' limit $start,$onepage";
$query_for_page = mysql_query ($sql_for_page);
while ($result = $query_for_page){
$list .= ''.$title.'
';
}
$content = str_replace ("{ articletable }",$list,$content);
if (is_file ($indexpath)){
@unlink ($indexpath); //若文件已存在,則删除
}
$handle = fopen ($indexpath,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($indexpath)){
echo "文件:".$indexpath."不可寫,請檢查其屬性後重試!"; //修改爲echo
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
echo "生(shēng)成文件".$indexpath."失敗!"; //修改爲echo
}
fclose ($handle); //關閉指針
}
fclose ($fp);
die ("生(shēng)成分(fēn)頁文件完成,如生(shēng)成不完全,請檢查文件權限系統後重新生(shēng)成!");
?>
大(dà)緻思路如此,其中(zhōng)如其它數據生(shēng)成,數據輸入輸出檢查,分(fēn)頁内容指向等可酌情在頁面中(zhōng)加入。
在實際文章系統處理過程當中(zhōng),還有許多問題有待考慮,與動态頁面不同之處,需注意的地方還有很多。但大(dà)緻思路即是如此,其它方面可舉一(yī)反三而得。
用PHP制作靜态網站的模闆框架
----------------------------------------------------
模闆能夠改善網站的結構。本文闡述如何通過PHP 4的一(yī)個新功能和模闆類,在由大(dà)量靜态HTML頁面構成的網站中(zhōng)巧妙地運用模闆控制頁面布局。
提綱:
===================================
分(fēn)離(lí)功能和布局
避免頁面元素重複
靜态網站的模闆框架
===================================
分(fēn)離(lí)功能和布局
首先我(wǒ)(wǒ)們來看看應用模闆的兩個主要目的:
分(fēn)離(lí)功能(PHP)和布局(HTML)
避免頁面元素重複
第一(yī)個目的是談論得最多的目的,它設想的情形是:一(yī)組程序員(yuán)編寫用于生(shēng)成頁面内容的PHP腳本,同時另一(yī)組設計人員(yuán)設計HTML和圖形以控制頁面的最終外(wài)觀。分(fēn)離(lí)功能和布局的基本思想就是使得這兩組人能夠各自編寫和使用獨立的一(yī)組文件:程序員(yuán)隻需關心那些隻包含PHP代碼的文件,無需關心頁面的外(wài)觀;而頁面設計人員(yuán)可以用自己最熟悉的可視化編輯器設計頁面布局,無需擔心破壞任何嵌入到頁面的PHP代碼。
如果你曾經看過幾個關于PHP模闆的教程,那麽你應該已經明白(bái)模闆的工(gōng)作機制。考慮一(yī)個簡單的頁面局部:頁面的上方是頁頭,左邊是導航條,其餘部分(fēn)是内容區域。這種網站可以擁有如下(xià)模闆文件:
<!-- main.htm -->
<html>
<head><title>模闆示例</title></head>
<body>
<table><tr><td>{HEADER}</td></tr>
<tr><td>{LEFTNAV}</td><td>{CONTENT}</td></tr>
</table>
</body></html>
<!-- header.htm -->
<img src="http://www.abcdown.net/InfoView/sitelogo.jpg">
<!-- leftnav.htm -->
<br><a href="foo">Foo</a>
<br><a href="bar">Bar</a>
可以看出頁面如何由這些模闆構造而成:main模闆控制着整個頁面的布局;header模闆和leftnav模闆控制着頁面的公共元素。花括号“{}”裏面的标識符是内容占位符。使用模闆最主要的好處在于界面設計者能夠按照自己的意願編輯這些文件,比如設置字體(tǐ)、修改顔色和圖形,或者完全地改變頁面的布局。界面設計者可以用任何普通HTML編輯器或者可視化工(gōng)具編輯這些頁面,因爲這些文件都隻包含HTML代碼,沒有任何PHP代碼。
PHP代碼全部保存到單獨的文件中(zhōng),這個文件也就是由頁面URL實際調用的文件。Web服務器通過PHP引擎解析該文件,然後把結果返回給浏覽器。一(yī)般地,PHP代碼總是動态地生(shēng)成頁面内容,比如查詢數據庫或者執行某種計算等。下(xià)面是一(yī)個例子:
<?php
// example.php
require('class.FastTemplate.php');
$tpl = new FastTemplate('.');
$tpl->define( array( 'main' => 'main.htm',
'header' => 'header.htm',
'leftnav' => 'leftnav.htm' ) );
// 此處的PHP代碼設置$content使其包含合适的頁面内容
$tpl->assign('CONTENT', $content);
$tpl->parse('HEADER', 'header');
$tpl->parse('LEFTNAV', 'leftnav');
$tpl->parse('MAIN', 'main');
$tpl->FastPrint('MAIN');
?>
這裏我(wǒ)(wǒ)們使用的是流行的FastTemplate模闆類,但其基本思路對于其他許多模闆類來說都一(yī)樣。首先你實例化一(yī)個類,告訴它到哪裏去(qù)尋找模闆文件以及哪一(yī)個模闆文件與頁面的哪部分(fēn)對應;接下(xià)來是生(shēng)成頁面内容,把結果賦予内容的标識符;然後,依次解析各個模闆文件,模闆類将執行必要的替換操作;最後把解析結果輸出到浏覽器。
這個文件完全由PHP代碼構成,不包含任何HTML代碼,這是它最大(dà)的優點。現在,PHP程序員(yuán)可以集中(zhōng)精力編寫生(shēng)成頁面内容的代碼,而不必爲了如何生(shēng)成HTML去(qù)正确地格式化最終頁面而擔心。
你可以使用這種方法和上面的文件構造出一(yī)個完整的網站。如果PHP代碼是以URL中(zhōng)的查詢字符串爲基礎生(shēng)成頁面内容,例如http://www.foo.com/example.php?article=099,你可以據此構造出一(yī)個完整的雜(zá)志(zhì)網站。
很容易看出采用模闆還有第二個好處。如上例所示,頁面左邊的導航條單獨保存爲一(yī)個文件,我(wǒ)(wǒ)們隻需編輯這一(yī)個模闆文件就可以改變網站所有頁面左邊的導航條。
避免頁面元素重複
“這确實不錯”,你也許會想,“我(wǒ)(wǒ)的網站主要就是由大(dà)量的靜态頁面構成。現在我(wǒ)(wǒ)可以從所有頁面中(zhōng)删除它們的公共部分(fēn),要更新這些公共部分(fēn)實在太麻煩了。以後我(wǒ)(wǒ)就可以用模闆制作出很容易維護的統一(yī)頁面布局。”但事情并非這麽簡單,“大(dà)量的靜态頁面”道出了問題的所在。
請考慮上面的例子。這個例子實際上隻有一(yī)個example.php頁面,它之所以能夠生(shēng)成整個網站的所有頁面,是因爲它利用了URL中(zhōng)的查詢字符串從數據庫之類的信息源動态地構造出頁面。
我(wǒ)(wǒ)們之中(zhōng)的大(dà)多數人所運行的網站并不一(yī)定都有數據庫支持。我(wǒ)(wǒ)們的網站大(dà)多數由靜态頁面構成,然後用PHP在這裏、那裏加上一(yī)些動态功能,比如搜索引擎、反饋表單等。那麽,如何在這種網站上應用模闆呢?
最簡單的方法是爲每一(yī)個頁面複制一(yī)份PHP文件,然後在每一(yī)個頁面中(zhōng)把PHP代碼裏代表内容的變量設置成合适的頁面内容。例如,假設有三個頁面,它們分(fēn)别是主頁(home)、關于(about)和産品(product),我(wǒ)(wǒ)們可以用三個文件分(fēn)别生(shēng)成它們。這三個文件的内容都類如:
<?php
// home.php
require('class.FastTemplate.php');
$tpl = new FastTemplate('.');
$tpl->define( array( 'main' => 'main.htm',
'header' => 'header.htm',
'leftnav' => 'leftnav.htm' ) );
$content = "<p>歡迎訪問</p>
<img src=\"demo.jpg\">
<p>希望你能夠喜歡本網站</p>";
$tpl->assign('CONTENT', $content);
$tpl->parse('HEADER', 'header');
$tpl->parse('LEFTNAV', 'leftnav');
$tpl->parse('MAIN', 'main');
$tpl->FastPrint('MAIN');
?>
顯然,這種方法有三個問題:我(wǒ)(wǒ)們必須爲每一(yī)個頁面複制這些複雜(zá)的、牽涉到模闆的PHP代碼,這與重複公共頁面元素一(yī)樣使得頁面難以維護;現在文件又(yòu)混合了HTML和PHP代碼;爲内容變量賦值将變得非常困難,因爲我(wǒ)(wǒ)們必須處理好大(dà)量的特殊字符。
解決這個問題的關鍵就在于分(fēn)離(lí)PHP代碼和HTML内容,雖然我(wǒ)(wǒ)們不能從文件中(zhōng)删除所有的HTML内容,但可以移出絕大(dà)多數PHP代碼。
靜态網站的模闆框架
首先,我(wǒ)(wǒ)們象前面一(yī)樣爲所有的頁面公用元素以及頁面整體(tǐ)布局編寫模闆文件;然後從所有的頁面删除公共部分(fēn),隻留下(xià)頁面内容;接下(xià)來再在每個頁面中(zhōng)加上三行PHP代碼,如下(xià)所示:
<?php
<!-- home.php -->
<?php require('prepend.php'); ?>
<?php pageStart('Home'); ?>
<h1>你好</h1>
<p>歡迎訪問</p>
<img src="http://www.abcdown.net/InfoView/demo.jpg">
<p>希望你能夠喜歡本網站</p>
<?php pageFinish(); ?>
?>
這種方法基本上解決了前面提到的各種問題。現在文件裏隻有三行PHP代碼,而且沒有任何一(yī)行代碼直接涉及到模闆,因此要改動這些代碼的可能性極小(xiǎo)。此外(wài),由于HTML内容位于PHP标記之外(wài),所以也不存在特殊字符的處理問題。我(wǒ)(wǒ)們可以很容易地将這三行PHP代碼加入到所有靜态HTML頁面中(zhōng)。
require函數引入了一(yī)個PHP文件,這個文件包含了所有必需的與模闆相關的PHP代碼。其中(zhōng)pageStart函數設置模闆對象以及頁面标題,pageFinish函數解析模闆然後生(shēng)成結果發送給浏覽器。
這是如何實現的呢?爲什麽在調用pageFinish函數之前文件中(zhōng)的HTML不會發送給浏覽器?答案就在于PHP 4的一(yī)個新功能,這個功能允許把輸出到浏覽器的内容截獲到緩沖區之中(zhōng)。讓我(wǒ)(wǒ)們來看看prepend.php的具體(tǐ)代碼:
<?php
require('class.FastTemplate.php');
function pageStart($title = '') {
GLOBAL $tpl;
$tpl = new FastTemplate('.');
$tpl->define( array( 'main' => 'main.htm',
'header' => 'header.htm',
'leftnav'=> 'leftnav.htm' ) );
$tpl->assign('TITLE', $title);
ob_start();
}
function pageFinish() {
GLOBAL $tpl;
$content = ob_get_contents();
ob_end_clean();
$tpl->assign('CONTENT', $content);
$tpl->parse('HEADER', 'header');
$tpl->parse('LEFTNAV', 'leftnav');
$tpl->parse('MAIN', 'main');
$tpl->FastPrint('MAIN');
}
?>
pageStart函數首先創建并設置了一(yī)個模闆實例,然後啓用輸出緩存。此後,所有來自頁面本身的HTML内容都将進入緩存。pageFinish函數取出緩存中(zhōng)的内容,然後在模闆對象中(zhōng)指定這些内容,最後解析模闆并輸出完成後的頁面。
這就是整個模闆框架全部的工(gōng)作過程了。首先編寫包含了網站各個頁面公共元素的模闆,然後從所有頁面中(zhōng)删除全部公共的頁面布局代碼,代之以三行永遠無需改動的PHP代碼;再把FastTemplate類文件和prepend.php加入到包含路徑,這樣你就得到了一(yī)個頁面布局可以集中(zhōng)控制的網站,它有着更好的可靠性和可維護性,而且網站級的大(dà)範圍修改也變得相當容易。
本文下(xià)載包包含了一(yī)個可運行的示例網站,它的代碼注釋要比前面的代碼注釋更詳細一(yī)些。FastTemplate類可以在http://www.thewebmasters.net/找到,最新的版本号是1.1.0,那裏還有一(yī)個用于保證該類在PHP 4中(zhōng)正确運行的小(xiǎo)補丁。本文下(xià)載代碼中(zhōng)的類已經經過該補丁的修正。
PHP簡易生(shēng)成靜态頁面
<?php
/*
* 文件名:index.php
*/
require "conn.php";
$query = "select * from news order by datetime desc";
$result = mysql_query($query);
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
<title>NEWS</title>
</head>
<body>
<table width="500" border="1" align="center">
<tr>
<td>标題</td>
<td width="200">發布時間</td>
</tr>
<?
while($re = mysql_fetch_array($result)){
?>
<tr>
<td><a href="<?= $re["newsid"].".html"?>"><?= $re["title"]?></a></td>
<td><?= $re["datetime"]?></td>
</tr>
<?
}
?>
<tr>
<td> </td>
<td><a href="addnews.php">添加新聞</a></td>
</tr>
</table>
</body>
</html>
--------------------------------------------------------------------------
<?php
/*
文件名:AddNews.php
簡易動态添加生(shēng)成靜态新聞頁面
#
# 表的結構 `news`
#
CREATE TABLE `news` (
`newsid` int(11) NOT NULL auto_increment,
`title` varchar(100) NOT NULL default '',
`content` text NOT NULL,
`datetime` datetime NOT NULL default '0000-00-00 00:00:00',
KEY `newsid` (`newsid`)
) TYPE=MyISAM AUTO_INCREMENT=11 ;
*/
if(isset($_POST["title"])){
$title = $_POST["title"];
$content = $_POST["content"];
//定義模版文件的内容,可用其它方法
$filecontent = '<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
<title>{title}</title>
</head>
<body>
<table width="500" border="1" align="center">
<tr>
<td align="center"><strong>{title}</strong></td>
</tr>
<tr>
<td>{content}</td>
</tr>
<tr>
<td align="right">{datetime}</td>
</tr>
</table>
</body>
</html>
';
$datetime = date("Y-m-d H:i:s");
$query = "insert into news values('','".$title."','".$content."','".$datetime."')";
require "conn.php";//連接數據庫
$result = mysql_query($query) or die(mysql_error());
if($result){
$id = mysql_insert_id();
$filename = $id.".html";
if($fp = fopen($filename, "w")){//新建文件,成功後添加内容
$filecontent = str_replace("{title}", $title, $filecontent);
$filecontent = str_replace("{content}", $content, $filecontent);
$filecontent = str_replace("{datetime}", $datetime, $filecontent);
if(!fwrite($fp, $filecontent)){//把内容寫入文件
$query = "delete from news where newsid=".$id;
$result = mysql_query($query) or die(mysql_error());
fclose($fp);
unlink($filename);
echo "<script>alert('Add news failed!');location.href='index.php';</script>";
exit;
}else {
echo "<script>alert('Add news successed!');location.href='index.php';</script>";
}
}
}
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=??????">
<title>添加</title>
</head>
<body>
<form name="form1" method="post" action="">
<table width="500" border="1" align="center">
<tr>
<td>标題</td>
<td><input name="title" type="text" id="title" size="40"></td>
</tr>
<tr>
<td>内容</td>
<td><textarea name="content" cols="45" rows="6" id="content"></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="Submit" value="提交"></td>
</tr>
</table>
</form>
</body>
</html>
PHP生(shēng)成靜态頁面詳解
應用實例:
http://xjtusky.net/down
說明:有一(yī)部分(fēn)功能還沒有完全做好,修改中(zhōng),有興趣的朋友可以看看下(xià)面這篇文章,看
完了一(yī)定要說好!生(shēng)成頁面的速度快的~~~呵呵。下(xià)面文章中(zhōng)一(yī)些地方請自行修改!
PHP生(shēng)成靜态頁面詳解
http://xjtusky.net/article/htmld ... /article_594_1.html
看到很多朋友在各個地方發帖問PHP生(shēng)成靜态文章系統的方法,以前曾做過這樣一(yī)個系
統,遂談些看法,以供各位參考。好了,我(wǒ)(wǒ)們先回顧一(yī)些基本的概念。
一(yī),PHP腳本與動态頁面。
PHP腳本是一(yī)種服務器端腳本程序,可通過嵌入等方法與HTML文件混合,也可以類,函
數封裝等形式,以模闆的方式對用戶請求進行處理。無論以何種方式,它的基本原理是這
樣的。由客戶端提出請求,請求某一(yī)頁面----->WEB服務器引入指定相應腳本進行處理
----->腳本被載入服務器----->由服務器指定的PHP解析器對腳本進行解析形成H
TML語言形式---->将解析後的HTML語句以包的方式傳回給浏覽器。由此不難看出,在
頁面發送到浏覽器後,PHP就不存在了,已被轉化解析爲HTML語句。客戶請求爲一(yī)動态文件
,事實上并沒有真正的文件存在在那裏,是PHP解析而成相對應的頁面,然後發送回浏覽器
。這種頁面處理方式被稱爲“動态頁面”。
二,靜态頁面。
靜态頁面是指在服務器端确實存在的僅含HTML以及JS,CSS等客戶端運行腳本的頁面。
它的處理方式是。由客戶端提出請求,請求某一(yī)頁面---->WEB服務器确認并載入某一(yī)
頁面---->WEB服務器将該頁面以包的形式傳遞回浏覽器。由這一(yī)過程,我(wǒ)(wǒ)們對比一(yī)下(xià)
動态頁面,即可方現。動态頁面需由WEB服務器的PHP解析器進行解析,而且通常還需連接
數據庫,進行數據庫存取操作,然後才能形成HTML語言信息包;而靜态頁面,無須解析,
無須連接數據庫,直接發送,可大(dà)大(dà)減輕服務器壓力,提高服務器負載能力,大(dà)幅提供頁
面打開(kāi)速度和網站整體(tǐ)打開(kāi)速度。但其缺點是,不能動态地對請求進行處理,服務器上必
須确實存在該文件。
三,模闆及模闆解析。
模闆即尚未填充内容html文件。例如:
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
temp.html
<HTML>
<TITLE>{title}</TITLE>
<BODY>
this is a {file} file's templets
</BODY>
</HTML>
PHP處理:
templetest.php
<?php
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,<br>author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{file}",$file,$content);
$content .= str_replace ("{title}",$title,$content);
echo $content;
?>
模闆解析處理,即将經PHP腳本解析處理後得出的結果填充(content)進模闆的處理過
程。通常借助于模闆類。目前較流行的模闆解析類有phplib,smarty,fastsmarty等等。
模闆解析處理的原理通常爲替換。也有些程序員(yuán)習慣将判斷,循環等處理放(fàng)進模闆文件中(zhōng)
,用解析類處理,典型應用爲block概念,簡單來說即爲一(yī)個循環處理。由PHP腳本指定循
環次數,如何循環代入等,再由模闆解析類具體(tǐ)實施這些操作。
好了,對比過靜态頁面與動态頁面各自的優劣,現在我(wǒ)(wǒ)們就來說說,如何用PHP生(shēng)成靜
态文件。
PHP生(shēng)成靜态頁面并不是指PHP的動态解析,輸出HTML頁面,而是指用PHP創建HTML頁面
。同時因爲HTML的不可寫性,我(wǒ)(wǒ)們創建的HTML若有修改,則需删掉重新生(shēng)成即可。(當然你
也可以選擇用正則進行修改,但個人認爲那樣做倒不如删掉重新生(shēng)成來得快捷,有些得不
償失。)
言歸正傳。用過PHP文件操作函數的PHP FANS知(zhī)道,PHP中(zhōng)有一(yī)個文件操作函數fopen,
即打開(kāi)文件。若文件不存在,則嘗試創建。這即是PHP可以用來創建HTML文件的理論基礎。
隻要用來存放(fàng)HTML文件的文件夾有寫權限(即權限定義0777),即可創建文件。(針對UNIX
系統而言,Win系統無須考慮。)仍以上例爲例,若我(wǒ)(wǒ)們修改最後一(yī)句,并指定在test目錄
下(xià)生(shēng)成一(yī)個名爲test.html的靜态文件:
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
<?php
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,<br>author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{file}",$file,$content);
$content .= str_replace ("{title}",$title,$content);
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
實際應用中(zhōng)常見問題解決方案參考:
一(yī),文章列表問題:
在數據庫中(zhōng)創建字段,記錄文件名,每生(shēng)成一(yī)個文件,将自動生(shēng)成的文件名存入數據
庫,對于推薦文章,隻需指向存放(fàng)靜态文件的指定文件夾中(zhōng)的該頁面即可。利用PHP操作處
理文章列表,存爲字符串,生(shēng)成頁面時替換此字符串即可。如,在頁面中(zhōng)放(fàng)置文章列表的
表格加入标記{articletable},而在PHP處理文件中(zhōng):
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
<?php
$title = "拓邁國際測試模闆";
$file = "TwoMax Inter test templet,<br>author:Matrix@Two_Max";
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$content .= str_replace ("{file}",$file,$content);
$content .= str_replace ("{title}",$title,$content);
// 生(shēng)成列表開(kāi)始
$list = '';
$sql = "select id,title,filename from article";
$query = mysql_query ($sql);
while ($result = mysql_fetch_array ($query)){
$list .= '<a href='.$root.$result['filename'].' target=_blank>'.$result[
'title'].'</a><br>';
}
$content .= str_replace ("{articletable}",$list,$content);
//生(shēng)成列表結束
// echo $content;
$filename = "test/test.html";
$handle = fopen ($filename,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($filename)){
die ("文件:".$filename."不可寫,請檢查其屬性後重試!");
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
die ("生(shēng)成文件".$filename."失敗!");
}
fclose ($handle); //關閉指針
die ("創建文件".$filename."成功!");
?>
二,分(fēn)頁問題。
如我(wǒ)(wǒ)們指定分(fēn)頁時,每頁20篇。某子頻(pín)道列表内文章經數據庫查詢爲45條,則,首先
我(wǒ)(wǒ)們通過查詢得到如下(xià)參數:1,總頁數;2,每頁篇數。第二步,for ($i = 0; $i < al
lpages; $i++),頁面元素獲取,分(fēn)析,文章生(shēng)成,都在此循環中(zhōng)執行。不同的是,die (
"創建文件".$filename."成功!";這句去(qù)掉,放(fàng)到循環後的顯示,因爲該語句将中(zhōng)止程序
執行。例:
Code: [點擊這裏把以下(xià)内容複制到剪貼闆]
<?php
$fp = fopen ("temp.html","r");
$content = fread ($fp,filesize ("temp.html"));
$onepage = '20';
$sql = "select id from article where channel='$channelid'";
$query = mysql_query ($sql);
$num = mysql_num_rows ($query);
$allpages = ceil ($num / $onepage);
for ($i = 0;$i<$allpages; $i++){
if ($i == 0){
$indexpath = "index.html";
} else {
$indexpath = "index_".$i."html";
}
$start = $i * $onepage;
$list = '';
$sql_for_page = "select name,filename,title from article where channel='
$channelid' limit $start,$onepage";
$query_for_page = mysql_query ($sql_for_page);
while ($result = $query_for_page){
$list .= '<a href='.$root.$result['filename'].' target=_blank>'.$titl
e.'</a><br>';
}
$content = str_replace ("{articletable}",$list,$content);
if (is_file ($indexpath)){
@unlink ($indexpath); //若文件已存在,則删除
}
$handle = fopen ($indexpath,"w"); //打開(kāi)文件指針,創建文件
/*
檢查文件是否被創建且可寫
*/
if (!is_writable ($indexpath)){
echo "文件:".$indexpath."不可寫,請檢查其屬性後重試!"; //修改爲echo
}
if (!fwrite ($handle,$content)){ //将信息寫入文件
echo "生(shēng)成文件".$indexpath."失敗!"; //修改爲echo
}
fclose ($handle); //關閉指針
}
fclose ($fp);
die ("生(shēng)成分(fēn)頁文件完成,如生(shēng)成不完全,請檢查文件權限系統後重新生(shēng)成!");
?>
大(dà)緻思路如此,其中(zhōng)如其它數據生(shēng)成,數據輸入輸出檢查,分(fēn)頁内容指向等可酌情在
頁面中(zhōng)加入。
在實際文章系統處理過程當中(zhōng),還有許多問題有待考慮,與動态頁面不同之處,需注
意的地方還有很多。但大(dà)緻思路即是如此,其它方面可舉一(yī)反三而得。