https://www.smarty.net/
https://www.smarty.net/docs/zh_CN/
1. smarty概述
smarty是目前使用最多的一個(gè)模板引擎
什么是模板引擎?
通過(guò)代碼說(shuō)明:
舉例子,沒(méi)有使用模板引擎的時(shí)候,寫代碼的方式:
需求:查詢數(shù)據(jù)庫(kù)的用戶列表,并在頁(yè)面中顯示出來(lái)


在公司開發(fā)項(xiàng)目的時(shí)候,是有分工的
如果按照上面編寫代碼的話,
- 不便于維護(hù),前端的人員不懂php的語(yǔ)法
-
這樣寫的話,也不符合現(xiàn)在最流行的MVC模式
按照MVC的規(guī)范,分為3層
image.png
使用smarty模板引擎,將php分配給html文件的數(shù)據(jù),顯示出來(lái)
模板引擎的核心就是,將php代碼(業(yè)務(wù)邏輯代碼) 和 數(shù)據(jù)顯示 相分離
2. smarty入門案例
-
下載smarty
image.png -
解壓
image.png
3. 將libs核心類庫(kù)拷貝到我們的項(xiàng)目目錄中,為了和其他的類庫(kù)區(qū)分,將其重命名為:smarty

-
將smarty里面的Smarty.class.php 引入到我們的php文件,并實(shí)例化
image.png
入門案例:
- 先指定將變量分配到哪個(gè)模板文件中
- 再分配數(shù)據(jù)
-
顯示
image.png
在模板中,如何使用php分配過(guò)來(lái)的變量呢?
通過(guò)模板標(biāo)簽實(shí)現(xiàn)顯示的,默認(rèn)的標(biāo)簽{$變量名} <?php ?>

能不能分配數(shù)組呢?

在模板中這樣使用數(shù)組:

還可以分配對(duì)象到模板


3. smarty的原理:
我們刷新項(xiàng)目,發(fā)現(xiàn)多了一個(gè)templates_c目錄


于是我們總結(jié)一下,smarty的原理:
php文件將html文件包含,生成一個(gè)混合的編譯文件.show.html.php
自定義模板引擎:
需求:能夠?qū)崿F(xiàn)在php文件中分配變量,并能夠在html模板中顯示php分配過(guò)來(lái)的變量
我們這樣設(shè)計(jì):
成員方法1:分配變量的功能
成員方法2:顯示模板的功能
思路分析:先將html模板文件加載到混合文件中,再將其中的{$name}類型的數(shù)據(jù)替換


模板文件的內(nèi)容:

替換模板中標(biāo)簽:

4. 模板中的變量來(lái)源
(1)最常見的是php文件分配過(guò)來(lái)的變量
(標(biāo)量、數(shù)組、對(duì)象)
(2)還可以使用配置文件的變量
什么是配置文件呢?
現(xiàn)在有3張圖片

如果一天,圖片的路徑變化了,我們需要將所有img標(biāo)簽里面的src屬性的值都替換
這樣做效率是比較低的
我們可以通過(guò)配置文件修改,只需要改一下配置,所有的圖片路徑都會(huì)跟著變化
在smarty中,使用配置文件(系統(tǒng))
-
先告訴smarty我的配置文件在哪里
image.png -
定義配置文件里面的信息
image.png -
在模板中使用配置文件里面定義的數(shù)據(jù)、信息
(1)先加載配置文件{config_load}
(2)通過(guò){#配置名稱#}
image.png
(3)還可以使用smarty的保留變量
{$smarty.now} 獲得當(dāng)前的時(shí)間戳
{$smarty.const.常量名} 獲得常量的值
{$smarty.config.配置名} 獲得配置文件中的配置信息
{$smarty.current_dir} 獲得當(dāng)前目錄

5. smarty的一些常用配置
(1)修改模板、編譯文件路徑
有些公司會(huì)將template目錄定義為tpl/tpls
將templates_c目錄定義為tpls_c
模板文件的類型改為 .tpl

但是修改之后還應(yīng)該告訴smarty,否則smarty找不到路徑了

(2)修改模板標(biāo)簽式 {}
有時(shí)候可能會(huì)和JavaScript的語(yǔ)法沖突,所以通常會(huì)修改模板標(biāo)簽

6. smarty中的變量調(diào)節(jié)器
smarty中的變量調(diào)節(jié)器就是對(duì)某個(gè)變量的值,進(jìn)行修改、格式化等處理
(1)date_format 格式化日期、時(shí)間

(2)capitalize 每個(gè)單詞的首字母大寫


(3)count_chararcters 統(tǒng)計(jì)每個(gè)單詞的字符的個(gè)數(shù)

(4)default 如果沒(méi)有定義變量、或者為空的時(shí)候,設(shè)置默認(rèn)值

(5)escape 轉(zhuǎn)碼
默認(rèn)是實(shí)體轉(zhuǎn)碼,將< > 等這些符號(hào)轉(zhuǎn)換成html的實(shí)體符號(hào)


還可能會(huì)用到url轉(zhuǎn)碼


(6)indent:字符縮進(jìn),縮進(jìn)的字符使用空白代替


(7)truncate:字符串截取
參數(shù)1:截取的長(zhǎng)度
參數(shù)2:截取之后,追加的字符(...)
參數(shù)3:true截取精確到字符個(gè)數(shù)
參數(shù)4:true:截取到中間,false截取到末尾


7. 模板中使用流程語(yǔ)句
1. foreach循環(huán)
現(xiàn)在smarty3版本,

$data是循環(huán)的數(shù)組
$k $v分別是每循環(huán)一次獲得的下標(biāo)及元素的值
也兼容smarty2的語(yǔ)法
注意:from=循環(huán)的數(shù)組
每循環(huán)一次將數(shù)組的下標(biāo)賦值給k變量,將數(shù)組的值賦值給v變量

foreachelse 標(biāo)簽指定如果沒(méi)有查詢到數(shù)據(jù)的時(shí)候,提示的信息
注意:嵌套在foreach標(biāo)簽里面,沒(méi)有結(jié)束標(biāo)記

if、elseif、else

for循環(huán)
<{for $i=1 to 10}>
step設(shè)置步長(zhǎng)值

include:引入外部文件
一個(gè)網(wǎng)站通常會(huì)有公共的頭部(logo、導(dǎo)航等)
公共的底部:(版權(quán)信息、聯(lián)系我們等)
我們可以將這些公共的信息保存到一個(gè)公共的文件、誰(shuí)需要誰(shuí)加載

在模板中使用include標(biāo)簽引入

模板繼承
通常也是一個(gè)公共的模板,可以被其他模板繼承并重寫內(nèi)容
1. 先定義一個(gè)父級(jí)模板、子級(jí)模板

-
在父級(jí)模板聲明被繼承以及能夠被重寫的部分
通過(guò)block標(biāo)簽聲明,默認(rèn)是被字模板重寫
image.png
3. 在子級(jí)模板中繼承父級(jí)模板的內(nèi)容,并重寫
首先聲明繼承的是哪個(gè)模板
extends聲明

- block標(biāo)簽?zāi)J(rèn)重寫父級(jí)模板的內(nèi)容,我們可以通過(guò) append、prepend屬性
設(shè)置追加寫

literal標(biāo)簽,告訴smarty,literal包起來(lái)的內(nèi)容,不使用smarty解析


8. smarty的緩存
1. 簡(jiǎn)單復(fù)習(xí):
PDO數(shù)據(jù)庫(kù)擴(kuò)展
- 開啟擴(kuò)展、重啟Apache
- new PDO()
- 執(zhí)行增刪改查
Smarty模板引擎 - 下載smarty類庫(kù)
- new Smarty;
- 分配數(shù)據(jù):assign
- 顯示內(nèi)容:display
需求:
我有一數(shù)據(jù)庫(kù)phone,兩張表:goods、category
將商品表的商品信息(id、商品名稱、商品價(jià)格)查詢并顯示成一格列表
步驟: -
命令DAOPDO這個(gè)類去查詢數(shù)據(jù)
image.png
-
命令smarty顯示數(shù)據(jù)
image.png
image.png
2. smarty的緩存
先查看一下IE瀏覽器的歷史記錄文件

思考?ie瀏覽器為什么要將這些文件保存到本地?
便于下次再訪問(wèn)該文件的時(shí)候,提高速度
3. 緩存圖例:
(1)使用緩存以前的代碼是這樣寫的:

缺點(diǎn)就是:
每次請(qǐng)求,都要請(qǐng)求數(shù)據(jù)庫(kù),眾所周知,數(shù)據(jù)庫(kù)不在本地,可能在美國(guó)、香港、杭州
所以這樣的效率、執(zhí)行速度是比較慢的
考慮將第一次請(qǐng)求查詢到的數(shù)據(jù)保存到本地,這樣,當(dāng)用戶下次訪問(wèn) 或者 其他用戶訪問(wèn)goods_list.php文件的時(shí)候,直接讀取緩存的文件,速度更快
具體實(shí)現(xiàn):
- 首先,在smarty中開啟緩存,有三個(gè)步驟:
步驟1:直接將caching屬性設(shè)置為1,就表示開啟
步驟2:設(shè)置緩存的時(shí)間,過(guò)期之后銷毀
步驟3:設(shè)置緩存文件的保存目錄 -
測(cè)試一下,在瀏覽器訪問(wèn):goods_list.php
image.png
訪問(wèn)之后,會(huì)在我們項(xiàng)目的cache目錄生成一個(gè)緩存文件:

(2)開啟緩存之后的流程圖

4. 局部不緩存
舉例說(shuō)明:股票、價(jià)格等時(shí)時(shí)變化的數(shù)據(jù)能緩存嗎?不能
(1)概念:
一個(gè)網(wǎng)頁(yè)大部分是可以緩存,當(dāng)然一些小的地方(價(jià)格、時(shí)間等)這些時(shí)時(shí)變化的數(shù)據(jù)是不能緩存的,使用局部不緩存實(shí)現(xiàn)
(2)代碼實(shí)現(xiàn)insert標(biāo)簽:
在smarty中,局部不緩存是通過(guò){insert}標(biāo)簽實(shí)現(xiàn),原理就是{insert}每次都會(huì)執(zhí)行
語(yǔ)法格式:
{insert name=”函數(shù)名”}
這樣,每次都會(huì)執(zhí)行該函數(shù)
insert插入的函數(shù)不能隨便寫,有如下規(guī)范:
(1)文件命名規(guī)范:

函數(shù)命名規(guī)范:

參數(shù)規(guī)范:

在自定義函數(shù)里面如何接受傳遞的參數(shù)呢?

接下來(lái)通過(guò)id獲取商品價(jià)格

測(cè)試一下:

(2)單模板多緩存
- 創(chuàng)建一些測(cè)試數(shù)據(jù)
創(chuàng)建一個(gè)小說(shuō)表:novel
id title
create table novel(id int primary key auto_increment,title varchar(30))en
gine myisam default charset utf8;

-
在php文件中拿到所有數(shù)據(jù)
image.png
給模板分配過(guò)去:

模板顯示:

測(cè)試一下:


不管傳遞的參數(shù)是 0 1 2 返回的結(jié)果都是
安娜卡列尼娜
思考,什么原因?
就是因?yàn)殚_啟了緩存,每次請(qǐng)求都是讀取的緩存的內(nèi)容

如何實(shí)現(xiàn),一個(gè)模板根據(jù)傳遞參數(shù)的不同,生成多個(gè)緩存文件
通過(guò)smarty的單模板多緩存實(shí)現(xiàn)
在display()的時(shí)候設(shè)置,如果傳遞第二個(gè)參數(shù),就表示先查看緩存目錄里面有沒(méi)有根據(jù)該參數(shù)生成的緩存,如果沒(méi)有則創(chuàng)建一個(gè),如果有,則直接讀取緩存內(nèi)容

優(yōu)化:
-
既然已經(jīng)有緩存文件了,就不需要在去數(shù)據(jù)庫(kù)查詢了
image.png
所以上面查詢數(shù)據(jù)庫(kù)之前,應(yīng)該判斷一下是否有緩存
完整代碼novel.php:
<?php
header("Content-Type:text/html;charset=utf-8");
require './I_DAO.interface.php';
require './DAOPDO.class.php';
require './smarty/Smarty.class.php';
$option = array(
'host' => '127.0.0.1',
'dbname'=> 'php_3',
'user' => 'root',
'pass' => '',
'port' => 3306,
'charset'=> 'utf8'
);
//命令smarty分配數(shù)據(jù)到模板
$smarty = new Smarty();
//接收地址欄上傳遞的參數(shù)id
$id = isset($_GET['id'])?$_GET['id']:0;
//先判斷如果沒(méi)有緩存的時(shí)候才去數(shù)據(jù)庫(kù)查詢
if(!$smarty->isCached('novel.html',$id)){
//實(shí)例化PDO對(duì)象
$dao = DAOPDO::getSingleton($option);
//查詢數(shù)據(jù)
$sql = "SELECT * FROM novel";
$result = $dao -> getAll($sql);
//根據(jù)參數(shù)從數(shù)組中獲得該參數(shù)對(duì)應(yīng)的小說(shuō) (一維數(shù)組)
$novel = $result[$id];
}
//開啟緩存
$smarty -> caching = 1;
//設(shè)置緩存的有效期,單位是秒
$smarty -> cache_lifetime = 60;
//設(shè)置緩存文件的保存路徑
$smarty -> setCacheDir('./cache/');
//設(shè)置模板目錄
$smarty -> setTemplateDir('./tpls/');
$smarty -> assign("novel",$novel);
//命令smarty顯示內(nèi)容
$smarty -> display('novel.html',$id);
清除緩存:
$smarty -> clearCache() 刪除具體某一個(gè)緩存文件
$smarty-> clearAllCache() 刪除所有緩存















