PHP基础(025)---Smarty模板
Smarty模板 ---PHP 最早的MVC模板引擎
Smarty 软件包下载地址 : http://www.smarty.net/download
Smarty是基于MVC(Model - View - Controller )框架概念,由模型-视图-控制器构成:
- 视图 : 就是提供给用户的界面;
- 控制器 : 负责处理视图和模型的对应关系,并将视图收集的信息传递给对应的模型。
- 模型 : 对接收过来的信息进行处理,并将处理结果回传给视图。
Smarty 特点:
- 可以自行设置模板定界符,所以可以使用{} , {{}} , <?-- {} --> 等;
- 仅对修改过的模板文件进行重新编译;
- 模板中可以使用if/elseif/else/endif ;
- 内建缓存支持;
- 可自定义插件 ;
- 待补...
Smarty安装:
我这里下载的是“Smarty-3.1.18.zip”,先解压,再将解压得到的libs目录存到E:\XMAPP\htdocs\根目录(也可以存到其他地方或子文件夹中,只引入到smarty类库即可),并重新命名为"Smarty3" ;
测试第一个smarty程序"hello world " :
第一步:在Smarty3下面新建四个文件夹,如下:

第二步:将这四个文件夹更名分:templates, templates_c, configs 和 cache。(强烈建议分别在每个使用Smarty的程序中都单独定义这些目录。)
第三步:在E:\XMAPP\htdocs\Smarty3\templates目录下面,新建一个index.tpl文件(或html文件):
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 5 <title>{ $title }</title> 6 </head> 7 <body> 8 {$content} 9 </body> 10 </html>
第四步 :在E:\XMAPP\htdocs\根目录下新建一个"helloworld.php" ;然后在EditPlus点击浏览器阅览:
1 <?php 2 /* 定义服务器的绝对路径 */ 3 define('BASE_PATH','E:\XMAPP\htdocs\\'); //对着这个文件入径配置即可 :E:\XMAPP\htdocs\Smarty3\templates 4 /* 定义Smarty目录的绝地你路径 */ 5 define('SMARTY_PATH','Smarty3\\'); 6 /* 加载Smarty类库文件 */ 7 require BASE_PATH.SMARTY_PATH.'Smarty.class.php'; 8 /* 实例化一个Smarty对象 */ 9 $smarty = new Smarty; 10 /* 定义各个目录的路径 */ 11 $smarty->template_dir = BASE_PATH.SMARTY_PATH.'templates/'; 12 $smarty->compile_dir = BASE_PATH.SMARTY_PATH.'templates_c/'; 13 $smarty->config_dir = BASE_PATH.SMARTY_PATH.'configs/'; 14 $smarty->cache_dir = BASE_PATH.SMARTY_PATH.'cache/'; 15 /* 使用Smarty赋值方法将一对儿名称/方法发送到模板中 */ 16 $smarty->assign('title','第一个Smarty程序'); 17 $smarty->assign('content','Hello world ,你好! \'Smarty\'!'); 18 /* 显示模板 */ 19 $smarty->display('index.tpl'); //或者用html为后缀也行 20 ?>
输出: “Hello world,你好!'Smarty'! ”
Smarty配置:
因为在实际开发中,一个项目所使用到的页面可能有上百个,不能每个页面都要重写一遍Smarty.class.php文件的连接,也不能为每个页面都建4个标准的文件夹去运作程序。为了避免这种情况,那么就是要对smarty模板的位置和相关配置进行规划。定义配置文件config.php,并存到E:\XMAPP\htdocs\根目录下.
其代码如下:
1 <?php 2 /* 定义服务器的绝对路径 */ 3 define('BASE_PATH','E:\XMAPP\htdocs\\'); ////对着这个文件入径配置即可 E:\XMAPP\htdocs\Smarty3\ 4 /* 定义Smarty目录的绝地你路径 */ 5 define('SMARTY_PATH','Smarty3\\'); 6 /* 加载Smarty类库文件 */ 7 require BASE_PATH.SMARTY_PATH.'Smarty.class.php'; 8 /* 实例化一个Smarty对象 */ 9 $smarty = new Smarty; 10 /* 定义各个目录的路径 */ 11 $smarty->template_dir = BASE_PATH.SMARTY_PATH.'templates/'; 12 $smarty->compile_dir = BASE_PATH.SMARTY_PATH.'templates_c/'; 13 $smarty->config_dir = BASE_PATH.SMARTY_PATH.'configs/'; 14 $smarty->cache_dir = BASE_PATH.SMARTY_PATH.'cache/'; 15 /* 调试控制台 */ 16 //$smarty->debugging = true; 17 /* 定义定界符 */ 18 //$smarty->left_delimiter = '<{'; 19 //$smarty->right_delimiter = '}>'; 20 ?>
那么因此上面的"helloworld.php"代码就变为了:
1 <?php 2 /* 引入配置文件 */ 3 include_once"config.php"; 4 5 /* 使用Smarty赋值方法将一对儿名称/方法发送到模板中 */ 6 $smarty->assign('title','第一个Smarty程序'); 7 $smarty->assign('content','Hello world,你好!\'Smarty\'!'); 8 /* 显示模板 */ 9 $smarty->display('index.html'); //或者用html为后缀也行 10 ?>
Smarty模板的设计:
Smarty的特点是将用户界面和过程实现分离,让美工和程序员各司其职,互不干扰。
-》smarty模板文件是由一个页面中所有的静态元素,加上一些定界符"{...}"组成的。模板文件统一存放的位置是templates目录下。模板中的不允许出现PHP代码段。smarty模板中的所有注释,变量,函数等都要包含在定界符内。
-》注释:smarty中的注释和PHP注释类似,都不会显示在源代码当中。注释包含在两个星号"*"中间,格式如下: {* remark *}
-》变量 :
- 来自PHP页面中的变量,也就是assign()方法传过来的变量。
- 保留变量,相当于PHP中的预定义变量。(Smarty模板中使用的保留变量有:get,post,server,session,cookie,request,now,const,config )
- 从配置文件中读取数据,Smarty模板也可以通过配置文件来赋值。
- 第一种使用"#"号,将变量名置于两个"#"号中间,即可像普通变量一样调用配置文件内容。
- 第二种使用变量中的$smarty_config.来调用配置文件。
- 补充在tpl文件中加载conf文件的方法是在tpl文件的第一行输入" { config_load file="myconf.conf" } " ;
-》修饰变量(Variable modifers ) : 格式[变量名|修饰变量的方法名:参数1:参数2:参数3...],在对变量进行修饰时,不仅可以单独使用,也可以多个使用,每个方法之间同样用“|"来分隔,例如{$str|nl2br|upper}
修饰变量的常用方法名有caplitalize(首字母大写),count_characters:true/false(变量中的字符串个数。如果后面有参数true,则空格也被计算。否则忽略空格),upper(将变量改为大写),strip_tags(去掉所有html标签),等。
-》流程控制:
- {if}...{else}...{/if} + 常用运算符(<,>,/,=,!=,eq,ne,lt,lte,is even,is odd, not,mod,div by等修饰词修饰)
- {foreach name=foreach_name key=key item=item from=arr_name}...{/foreach} ---其中item和from是必要参数,不可省略
- {section name="sec_name" loop=$arr_name start=num step=nem}...{/section}
Smarty程序设计:
-》smarty中的常用方法:在PHP文件中除了assign,display方法,还有其它方法比较常用:
- void append() ---该方法向数组中追加元素
- void clear_all_assign() ---清除所有模板中的赋值
- void clear_assign() ---清除一个指定的赋值
- void config_load() ---加载配置文件
- string fetch() ---返回模板的输出内容,但不直接显示出来
- array get_config_vars() ---获取指定配置变量的值,如果没有参数,则返回一个所有配置变量的数组
- array get_template_vars() ---获取指定模板变量的值 ,如果没有参数,则返回一个所有模板变量的数组
- bool template_exists() ---检测指定的模板是否存在
-》smarty的配置变量:
- 常量: SMARTY_DIR ---用来保存Smarty类库的完整路径
- 变量: $template_dir ---模板目录
- 变量: $compile_dir ---编译目录
- 变量: $cache_dir ---缓存目录
- 变量:$config_dir ---配置目录
- 变量:$debugging---调试变量
- 变量: $caching---缓存变量
Smarty缓存:
1.在smarty中控制缓存
<?php
require('libs/Smarty.class.php');
$smarty= new Smarty;
//建立缓存
$smarty->caching=true; // 启用缓存
$smarty->cache_dir="./cache/"; //指定缓存目录
//缓存的生命周期
$smarty->cache_lifetime=60*60*24; //设置缓存时间为1天
$smarty->display('index.tpl'); //单个页面输出保存
//每个页面多个缓存
$smarty->display('index.tpl',$_GET["newsid"]); //通过id传递
?>
2.判断是否被缓存了:(下例中is_cache()和display()两个方法,使用的参数是相同的。)
if(!$smarty->is_cache('news.tpl',$_GET["newsid"])){
$smarty->assign(...);
}
$smarty->displary('news.tpl',$_GET["newsid"]);
3.清除缓存:
<?php
require('libs/Smarty.class.php');
$smarty= new Smarty();
$smarty->caching=true;
$smarty->clear_all_cache(); //清除所有的缓存文件
$smarty->clear_cache('index.tpl'); //清除某一模板的缓存
$smarty->clear_cache('index.tpl',"CACHEID"); //清除某一模板的多个缓存中指定缓存号的一个
$smarty->display('index.tpl');
?>
4.关闭局部缓存:
首先定义一个插件函数block.cacheless.php,并将其存放在smarty的plugins目录下,文件代码如下:
<?php
function smarty_block_cacheless($param,$content,&$smarty){
return $content;
}
?>
然后将Smarty的源文件Smarty_Compiler.class.php打开,找到下面的一句:
$this->_plugins['block'][$tag_command]=array($plugin_func,null,null,null,true); //将其最后一个参数改成flase
最后在test.tpl中编写相应的代码:
<{cacheless}> 此标签内是不需要缓存的内容<{/cacheless}>
备注:在相关的显示部分,例如实时比分,广告,时间等,使用<{cacheless}>。。。 <{/cacheless}>自定义的smarty块标记,关闭不需要缓存的内容。
其他内容补充代码:
<test.php>
<?php
include "./libs/Smarty.class.php"; //包含Smarty类库所在的文件
require("Page_class.php"); //包含分页类Page所在的文件
require("MyDB_class.php"); //包含数据库读取类所在的文件
$tpl = new Smarty(); //创建一个Smarty类的对象$tpl
$tpl->template_dir = "./templates/"; //设置所有模板文件存放的目录
$tpl->compile_dir = "./templates_c/"; //设置所有编译过的模板文件存放的目录
$tpl->cache_dir = "./cache/"; //设置存放Smarty缓存文件的目录
$tpl->caching=1; //设置开关Smarty缓存模板功能属性,这里为开启
$tpl->cache_lifetime=60*60; //设置模板缓存有效时间段的长度,这里为1小时
$tpl->left_delimiter = '<{'; //设置模板语言中的左结束符
$tpl->right_delimiter = '}>';
//下面的代码需要一个个的测试单元打开
$tpl->assign('title',"Smarty实现商品列表"); //将title中的字母转成大写
/*补充变量多个修改器
*{$articleTitle}
*{$articleTitle|upper|spacify}
*{$articleTitle|lower|spacify|truncate}
*{$articleTitle|lower|truncate:30|spacify}
*{$articleTitle|lower|spacify|truncate:30:". . ."}
*/
/*
* 1){include file="header.tpl"} {* body of template goes here *} {include file="footer.tpl"}
* 2)还可以{* 绝对路径或 $trusted_dir 的相对路径 *} {include_php file="/path/to/load_nav.php"}
* 3)smarty insert : 使模板的一部分不被缓存. 如果打开了缓存, insert 函数却不会被缓存,每次调用页面它们都会被动态加载,即使是在缓存页面中. 该特性可以广泛应用于广告条、投票、实时天气预报、搜索结果、反馈信息等区域.
* 4)smarty Literal 标签区域内的数据将被当作文本处理,此时模板将忽略其内部的所有字符信息. 该特性用于显示有可能包含大括号等字符信息的 javascript 脚本. 当这些信息处于 {literal}{/literal} 标签中时,模板引擎将不分析它们,而直接显示.
*
*/
//开始测试一:Smarty strip去除多余空格实例代码教程 - 用一个空格或一个给定字符替换所有重复空格,换行和制表符.
$tpl->assign('articleTitle', "Grandmother of\neight makes\t hole in one.");
//开始测试二:数组
// $contact=array( //将一个人的联系信息保存在一个关联数组中
// 'fax' => '555-222-9876',
// 'email' => 'gao@lampbrother.net',
// 'phone' => array(
// 'home' => '555-444-3333',
// 'cell' => '555-111-1234'
// )
// );
// $tpl->assign('contact', $contact); //将关联数组$contact分配到模板中使用
//
// $contact2=array( //将一个人的联系信息保存在一个索引数组中
// '555-222-9876',
// 'gao@lampbrother.net',
// array( '555-444-3333', '555-111-1234')
// );
// $tpl->assign('contact2', $contact2); //将索引数组$contact2分配到模板中使用
//
// $contact3=array( //使用索引和关联数组保存联系信息
// 'fax' => '555-222-9876',
// array('first'=>'gao@lampbrother.net','second'=>'feng@lampbrother.net'),
// 'phone' => array('555-444-3333','555-111-1234')
// );
// $tpl->assign('contact3', $contact3); //将混合数组$contact3分配到模板中使用
//开始测试三:循环 foreach; 测试四section
/*
* 模板的 section 用于遍历数组中的数据. section 标签必须成对出现. 必须设置 name 和 loop 属性. 名称可以是包含字母、数字和下划线的任意组合. 可以嵌套但必须保证嵌套的 name 唯一. 变量 loop (通常是数组)决定循环执行的次数. 当需要在 section 循环内输出变量时,必须在变量后加上中括号包含着的 name 变量. sectionelse 当 loop 变量无值时被执行.
*
*
*
*/
$contact4=array( //声明一个保存三个联系人信息的二维数组
array('name'=>'高某','fax'=>'1234','email'=>'gao@lampbrother.net','phone'=>'4321'),
array('name'=>'洛某','fax'=>'4567','email'=>'luo@lampbrother.net','phone'=>'7654'),
array('name'=>'峰某','fax'=>'8910','email'=>'feng@lampbrother.net','phone'=>'0198')
);
$tpl->assign('contact4', $contact4); //将关联数组$contact分配到模板中使用
//测试三完
//测试五开始
$id = array(1001,1002,1003);
$tpl->assign('custid',$id);
$fullnames = array('John Smith','Jack Jones','Jane Munson');
$tpl->assign('name',$fullnames);
$addr = array('253 N 45th', '417 Mulberry ln', '5605 apple st');
$tpl->assign('address',$addr);
$types = array(
array( 'home phone', 'cell phone', 'e-mail'),
array( 'home phone', 'web'),
array( 'cell phone')
);
$tpl->assign('contact_type', $types);
$info = array(
array('555-555-5555', '666-555-5555', 'john@myexample.com'),
array( '123-456-4', 'www.example.com'),
array( '0457878')
);
$tpl->assign('contact_info', $info);
//测试五结束
$tpl->display("test.tpl");
?>
<test.tpl>
<html>
<head><title><{$title|upper}></title></head>
<body>
<!-- this is a comment 这里是模板注释 -->
<{$articleTitle}>
<{$articleTitle|strip}>
<{$articleTitle|strip:" "}>
<!--
Grandmother of
eight makes hole in one.
Grandmother of eight makes hole in one.
Grandmother of eight makes hole in one.
-->
<p>访问从PHP中分配的关联数组:
电子邮件:<{$contact.email}> 家庭电话:<{$contact.phone.home}><br>
访问从PHP中分配的索引数组:
电子邮件:<{$contact2[1]}> 家庭电话:<{$contact2[2][0]}><br>
访问从PHP中分配的索引和关联混合数组:
第一个电子邮件:<{$contact3[0].first}> 家庭电话:<{$contact3.phone[0]}><br></p>
<!--测试三开始-->
<div>
<!--<table border="1" width="80%" align="center">
<caption><h1>联系人信息</h1></caption>
<tr>
<th>姓名</th><th>传真</th><th>电子邮件</th><th>联系电话</th>
</tr>
<{foreach from=$contact4 item=row}> <{* 外层foreach遍历数组$contact4 *}>
<tr> <{* 输出表格的行开始标记 *}>
<{foreach from=$row item=col}> <{* 内层foreach遍历数组$row *}>
<td><{$col}></td> <{* 以表格形式输出数组中的每个数据 *}>
<{/foreach}> <{* 内层foreach区块结束标记 *}>
</tr> <{* 输出表格的行结束标记 *}>
<{/foreach}> <{* 外层foreach区域的结束标记 *}>
</table>
<!--测试三结束--> -->
</div>
<div>
<!--测试四开始-->
<table border="1" width="80%" align="center">
<caption><h1>联系人信息</h1></caption>
<tr>
<th>姓名</th><th>传真</th><th>电子邮件</th><th>联系电话</th>
</tr>
<{section name=line loop=$contact4}> <{* 使用section遍历数组$contact *}>
<tr> <{* 输出表格的行开始标记 *}>
<td><{$contact4[line].name}></td> <{* 输出数组第二维中下标为name的元素值 *}>
<td><{$contact4[line].fax}></td> <{* 输出数组第二维中下标为fax的元素值*}>
<td><{$contact4[line].email}></td> <{* 输出数组第二维中下标为email的元素值*}>
<td><{$contact4[line].phone}></td> <{* 输出数组第二维中下标为phone的元素值*}>
</tr> <{* 输出表格的行结束标记 *}>
<{/section}> <{* section区域的结束标记 *}>
</table>
<!--测试四结束-->
</div>
<!--测试五开始-->
<div>
<{section name=customer loop=$custid}>
<hr>
id: <{$custid[customer]}><br />
name: <{$name[customer]}><br />
address: <{$address[customer]}><br />
<{section name=contact loop=$contact_type[customer]}>
<{$contact_type[customer][contact]}>: <{$contact_info[customer][contact]}><br />
<{/section}>
<{/section}>
</div>
<!--测试五结束-->
</body>
</html>
浙公网安备 33010602011771号