Smarty例項教程(5)

gaoshouma發表於2009-02-25

Smarty例程學習(原創)—-例項篇(一、使用php內建mysql語句)

Smarty例項教程 —-例項篇(一、使用PHP內建MYSQL函式)

從本節開始我們來學習一下如果把Smarty應用到實際的例子中. 為了演示說明,我將以前寫的一個站點作為例項來講來下.先說明一下, 我本人的美術功底不是很強,所以設計出來的頁面不太好看,大家就對付著看吧
在看本文之前,可以先看看indexbak.htm與newsbak.htm,它們是我們生成後的例圖。

一、 首先來說明一下我們將要使用到的資料庫,下面我先將資料庫原始檔給大家例出來:

======================================================================
CREATE DATABASE News;

USE News;

/****************************
*
* 表 名: tb_news_ch
* 用 途: 國內新聞表
*
****************************/
CREATE TABLE tb_news_ch
(
iNewsID interger(11) primary key auto_increment,
vcNewsTitle varchar(50) not null,
ltNewsContent longtext not null
);

/****************************
*
* 表 名: tb_news_in
* 用 途: 國際新聞表
*
****************************/
CREATE TABLE tb_news_in
(
iNewsID interger(11) primary key auto_increment,
vcNewsTitle varchar(50) not null,
ltNewsContent longtext not null
);

/****************************
*
* 表 名: tb_news_mu
* 用 途: 娛樂新聞表
*
****************************/

CREATE TABLE tb_news_mu
(
iNewsID interger(11) primary key auto_increment,
vcNewsTitle varchar(50) not null,
ltNewsContent longtext not null
);
======================================================================

我這裡簡單的將資料庫說明一下.

第一個問題:
大家可以看到,其實3個資料表的欄位名都一樣,那麼為什麼不把它們合併成一個資料表呢,答案很簡單:效率,在開發的時候我們可能感覺不出有什麼可提高效率的地方,不過大家想想,當這個網站執行一段時間後,它的新聞資料量就會變的很大,而且考慮到如果將來網站做大後可能將各個型別分離出來形成類似china.xxx.com, international.xxx.com, music.xxx.com,將每一欄目獨立分出去物理上做成一個單獨的站點,到那時如果新聞還是合起來放置的話就會造成資料庫瓶頸,所以針對當前的站點,我認為還是分開的比較合理.

第二個問題:
有人可能問了,你在欄位前加的i, vc,lt幹什麼用?這裡是按照欄位型別來命名的, 這也是一種良好風格的體現,將型別字首放在變數前,使用使用者不用看欄位定義就可以知道欄位是什麼型別,這是從微軟的匈牙利命名法中參考過來的,在資料庫設計時,我先將每種型別定義成1–3個字母,然後在每個欄位前加相應的程式碼來代表它的型別.像上邊,我將各個資料庫欄位型別定義為:

integer i
varchar vc
longtext lt
char c
….

在使用的時候,你可以往每個資料表中輸入5條資料記錄以備我們在除錯例項時使用.

二、示例站點目錄結構:

PHP程式碼:——————————————————————————–
+Web (站點根目錄)
|
|—-+comm (Smarty相關文件目錄)
| |
| |—-+plugins (Smarty外掛目錄)
| |—–Config_File.class.php (Smarty配置檔案)
| |—–Smarty.class.php (Smarty類主檔案)
| |—–Smarty_Compiler.class.php (Smarty編譯類檔案)
|
|—-+cache (Smarty快取目錄,*nix下保證讀寫許可權)
|
|—-+templates (站點模板檔案存放目錄)
| |
| |—-header.tpl(頁面頁頭模板檔案)
| |—-index.tpl(站點首頁模板檔案)
| |—-foot.tpl(頁面頁尾模板檔案)
| |—-news.tpl (新聞頁模板檔案)
|
|
|—-+templates_c (模板檔案編譯後存放目錄,*nix下保證讀寫許可權)
|
|—-+css (站點CSS檔案目錄)
|
|—-+image (站點圖片目錄)
|
|—-+media (站點Flash動畫存放目錄)
|
|—-indexbak.htm (首頁原始效果圖)
|
|—-newsbak,htm (新聞頁原始效果圖)
|
|—-index.php (Smarty首頁程式檔案)
|
|—-news.php (Smarty新聞顯示檔案)
|
|—-例程說明.txt (目錄說明)
|
|—-資料庫建立檔案.txt (資料庫的建立文件)

詳細情況請大家下載例項後對照結構圖。

——————————————————————————–

三、模板中的例項片段:

1. index.tpl:

index.tpl是站點首頁的模板類,開啟它的原始檔後我們可以首先看到這麼二句:
==================================================
1. <{*下面這一句為本頁面的頁面頭*}>
2. <{include file=”header.tpl”}>
==================================================
第 1 句大家都知道了,是模板註釋
第 2 句表示在當前位置要包含另一個檔案,什麼檔案呢,header.tpl,這裡的這個header.tpl是頁面的標準頁標頭檔案,把它單獨拿出來是為將這一部分獨立出來,以便在在其它頁面進行重用,習慣上要把頁標頭檔案寫在一個table中,但因為我的例項是早已做好的,所以有些不符合規範。

再來看最後一句:
=================================================
3. <{include file=”foot.tpl”}>
=================================================
不用說大家都明白了,就是包含一個頁尾檔案。

再看看國內新聞部分的模板程式碼:

=================================================
<table width=”100%” border=”0″ cellpadding=”0″ cellspacing=”0″ bgcolor=”#B9E9FF”>
<tr>
<td height=”115″ width=”10″></td>
<td valign=”top” width=”295″ bgcolor=”#B9E9FF”>
<{section name=loop loop=$News_CH}>
<li class=”newsfont”><a href=”news.php?type=1&id=<{$News_CH[loop].NewsID}>” class=”newsfont”><{$News_CH[loop].NewsTitle}></a>
<{/section}>
</td>
</tr>
</table>
=================================================

大家關鍵看<{section}>與<{/section}>,它們之外的那一部分是為了更好的理解程式碼的意思而列出來的。能看明白嗎?這裡將以前講過的內容複習一遍:定義了一個section迴圈模板塊,名字叫loop, 要迴圈的是$News_CH這個陣列,以<a href=”/xxxx”>處將為當前的新聞產生一個連結,地址為news.php?type=1&id=xxx,這裡的xxx是從資料庫裡提取的iNewsID,指的是要在新聞顯示頁裡顯示編號為id的新聞。$News_CH[loop].NewsTitle這種表示形式來看的懂吧?看不懂的話看看上一節講過的《Smarty例項教學 —程式設計》部分中的<{section}>語法。
也許大家對<{}>感覺有點陌生,這裡的<{}>為模板語句定義塊,在前2節我們都使用{},但因為這裡是具體的應用,所以就不取{}了,使用大家習慣的<{}>來表示,當然這在.php檔案中要設定的。

再看國際新聞與娛樂新聞的程式碼:

國際新聞:
================================================
<table width=”100%” border=”0″ cellpadding=”0″ cellspacing=”0″>
<tr>
<td width=”295″ height=”115″ valign=”top”>
<{section name=loop loop=$News_IN}>
<li class=”newsfont”><a href=”news.php?type=2&id=<{$News_IN[loop].NewsID}>” class=”newsfont”><{$News_IN[loop].NewsTitle}></a>
<{/section}>
</td>
</tr>
</table>
================================================

娛樂新聞:
================================================
<table width=”100%” border=”0″ cellpadding=”0″ cellspacing=”0″>
<tr>
<td width=”296″ height=”115″ valign=”top”>
<{section name=loop loop=$News_MU}>
<li class=”newsfont”><a href=”news.php?type=3&id=<{$News_MU[loop].NewsID}>” class=”newsfont”><{$News_MU[loop].NewsTitle}></a>
<{/section}>
</td>
</tr>
</table>
================================================

有沒有看出有什麼不同? loop部分不同,loop指的是要迴圈的陣列,這裡要注意的,不可將多個section的loop指定為同一個值,那樣的話Smarty進行分析模板的時候就會將兩個具有相同名字的section同時分析,生成兩個一樣的記錄。

看到這裡,有人就會產生疑問:迴圈塊我已經有了,我怎麼才能就它在當前位置只顯示我們想要的記錄數呢?這個問題簡單,我們對Smarty的section迴圈塊的迴圈次數控制是在.php檔案中控制要替換這個迴圈塊的陣列來決定的,在設計模板時我們不用考慮。

其次,我們再來看看news.tpl:

1. 看這一句:
<title><{$NewsTitle}> —-天驕資訊網</title>
將要顯示的新聞頁的標題顯示為新聞標題 + “—-天驕資訊網”
2. 新聞標題:
<div align=”center” class=”NewsTitle”><{$NewsTitle}></div>
這裡又設定了一個模板變數$NewsTitle,意思說要.php將$NewsTitle(包括標題欄)替換為資料庫中當前新聞的標題。
3. 新聞內容:
<p><{$NewsContext}></p>
這一句也容易,在當前位置顯示新聞內容。

當然,這裡只是簡單的將新聞列出來了,在實際應用時你還可以把文章出處,發表時間,作者,相關新聞一起列出來,這裡就不作多的討論了.

三、程式部分:

1. 大家先來看看index.php的原始檔,然後我們再來慢慢分析它的作用:

=============================================================
index.php
=============================================================
<?php
1. /*********************************************
*
* 檔名: index.php
* 作 用: 顯示例項程式
*
* 作 者: 大師兄
* Email: teacherli@163.com
*
*********************************************/
2. include_once(“./comm/Smarty.class.php”); //包含smarty類檔案
3. define(“NUM”, 5); //定義每次顯示的新聞條數

4. $smarty = new Smarty(); //建立smarty例項物件$smarty
$smarty->templates_dir = “./templates”; //設定模板目錄
$smarty->compile_dir = “./templates_c”; //設定編譯目錄
$smarty->cache_dir = “./cache”; //設定快取目錄
$smarty->cache_lifetime = 60 * 60 * 24; //設定快取時間
$smarty->caching = false; //這裡是除錯時設為false,釋出時請使用true
$smarty->left_delimiter = “<{“; //設定左邊界符
$smarty->right_delimiter = “}>”; //設定右邊界符

5. $db = mysql_connect(“localhost”, “root”, “”);
mysql_select_db(“News”, $db);

//這裡將處理國內新聞部分
6. $strQuery = “SELECT iNewsID, iNewsTitle FROM tb_news_CH ORDER BY iNewsID DESC”;
$result = mysql_query($strQuery);
$i = NUM;
7. while(($row = mysql_fetch_array($result)) && $i > 0)
{
$array[] = array(“NewsID”, substr($row[“iNewsID”], 0, 40),
“NewsTitle”, substr($row[“vcNewsTitle”], 0, 40));

$i–;
}
8. $smarty->assign(“News_CH”, $array);
9. unset($array);
mysql_free_result();

10. //這裡處理國際新聞部分
$strQuery = “SELECT iNewsID, iNewsTitle FROM tb_news_IN ORDER BY iNewsID DESC”;
$result = mysql_query($strQuery);
$i = NUM;
while(($row = mysql_fetch_array($result)) && $i > 0)
{
$array[] = array(“NewsID”, substr($row[“iNewsID”], 0, 40),
“NewsTitle”, substr($row[“vcNewsTitle”], 0, 40));

$i–;
}
$smarty->assign(“News_IN”, $array);
unset($array);
mysql_free_result();

11. //這裡將處理娛樂新聞部分
$strQuery = “SELECT iNewsID, iNewsTitle FROM tb_news_MU ORDER BY iNewsID DESC”;
$result = mysql_query($strQuery);
$i = NUM;
while(($row = mysql_fetch_array($result)) && $i > 0)
{
$array[] = array(“NewsID”, substr($row[“iNewsID”], 0, 40),
“NewsTitle”, substr($row[“vcNewsTitle”], 0, 40));

$i–;
}
$smarty->assign(“News_MU”, $array);
unset($array);
mysql_free_result();

mysql_close($db);

//編譯並顯示位於./templates下的index.tpl模板
12. $smarty->display(“index.tpl”);
?>

為了方便說明,我把每一個要說明的地方都標了號,下面就來說說每一個部分的作用:

1. 程式註釋, 風格問題,我多次在程式中加這個就是為了讓讀者也養成這種習慣.
2. 檔案包含. 這一句意思是把Smarty的類檔案包含到當前程式檔案中.
3. 常數定義: 定義NUM為5,為新聞顯示條數
4. 設定Smarty引數: 關於裡邊的引數大家可以參考上一節講過的,這裡只想特別說明一下$smarty->cache屬性,在我們的程式除錯過程中,要把它設定為false,正式釋出的時候將它設計為true就可以實現我們的程式快取效果.
5. 資料庫連線: 這一部分我不用說吧?標準的PHP語句.
6. 進行國內新聞查詢SQL語句: 標準的SQL語句,按新題編號降序排序.
7. while():
這一句控制將要顯示的新聞行數.首先給$i賦值為NUM,NUM為我們在開始外定義的一個常量, 在while()的開始判斷處使用$i>0 這個條件,while()每次迴圈時要將$i的值減1,這樣,當它完成5次迴圈時while就會結束.
這裡我們主要來看看$array[]這個陣列:
$array[]在理論上為一個二維陣列,也就是一個陣列中的元素為另一個陣列,像上例中,當while()語句結束時,$array就是一個包含5個陣列元素的陣列,而每一元素又是一個字元索引的陣列.而這些字元索引正是在模板中定義section迴圈塊的$news[loop]的屬性值,大家一定要注意這裡要與模板迴圈塊的屬性值相對應,否則將不能顯示出來!
在構建這個二維陣列時我們使用了一個substr()方法進行字元擷取,這個方法在這裡僅供參考,實際使用當中因為中文為全形字元,使用它時可能會造成亂碼,在以後的例子中我們將使用另一個網友與的csubstr()函式來實現字元擷取功能.

8. 對模板中的loop = $News_CH的section迴圈塊進行解析.
大家要注意,使用$smarty->assign(“News_CH”, $array),assign的第一個引數為section中的loop的值, 第二個引數為上面所建立的陣列.

9. 登出$array: $array[]在使用完後要登出,因為使用賦值語句對$array進行賦值時不會將它清空,而是將新陣列作為它的一個元素增加,為了不產生副作用,這裡使用unset()是必需的.

10. 國際新聞處理模組:
同國內新聞處理模組一樣,大家可以對比一下模板與這一段,找找其中有什麼關聯之處.

11. 娛樂新聞處理模組:同上,大家找找其中的關係.相信大家看完會有收穫的.

12. 處理並顯示index.tpl.

2. 下面再來看看news.php的原始檔:

========================================================
news.php
========================================================
<?php
/*********************************************
*
* 檔名: news.php
* 作 用: 新聞顯示程式
*
* 作 者: 大師兄
* Email: teacherli@163.com
*
*********************************************/
include_once(“./comm/Smarty.class.php”); //包含smarty類檔案
define(“NUM”, 5); //定義每次顯示的新聞條數

$smarty = new Smarty(); //建立smarty例項物件$smarty
$smarty->templates_dir = “./templates”; //設定模板目錄
$smarty->compile_dir = “./templates_c”; //設定編譯目錄
$smarty->cache_dir = “./cache”; //設定快取目錄
$smarty->cache_lifetime = 60 * 60 * 24; //設定快取時間
$smarty->caching = false; //這裡是除錯時設為false,釋出時請使用true
$smarty->left_delimiter = “<{“; //設定左邊界符
$smarty->right_delimiter = “}>”; //設定右邊界符

$db = mysql_connect(“localhost”, “root”, “”) or die(“資料庫連線錯誤!”);
mysql_select_db(“News”, $db);

$NewsID = $_GET[“id”]; //獲取新聞編號
$NewsType = $_GET[“type”]; //要顯示的新聞型別
switch($NewsType)
{
case 1:
$dbName = “tb_news_ch”;
break;
case 2:
$dbName = “tb_news_in”;
break;
case 3:
$dbName = “tb_news_mu”;
break;
}

$strQuery = “SELECT vcNewsTitle, ltNewsContent FROM ” . $dbName;
$result = mysql_query($strQuery) or die(“資料庫查詢錯誤!”);
if($row = mysql_fetch_array($result))
{
$smarty->assign(“NewsTitle”, $row[“vcNewsTitle”]);
$smarty->assign(“NewsContent”, $row[“ltNewsContent”]);

mysql_free_result($result);
$smarty->display(“news.tpl”);
}

mysql_close($db);

?>
這上面關於Smarty的程式語句主要只有3行:
==================================================================
$smarty->assign(“NewsTitle”, $row[“vcNewsTitle”]);
$smarty->assign(“NewsContent”, $row[“ltNewsContent”]);

mysql_free_result($result);
==================================================================

很簡單的將新聞頁中的NewsTitle, NewsContent替換成從資料庫中查詢出來的內容.

好了,關於這一講的Smarty例程學習的初級部分就講到這裡,相信大家學完後會對Smarty的用法有個基本的瞭解,下一節還使用個這個例子來講講如何使用phplib中的DB類來實現對模板的控制.


相關文章