smarty
一、 Introduction
模板技术,将php和html分开的技术。常用的模板引擎,smarty、template、fxl template、dwoo,其中,smarty是功能最强大,最常用的。Smarty是一个php的模板引擎技术,提供让程序逻辑与页面显示代码分开的功能。特点,速度快,编译型,缓存技术,插件技术,强大的表现逻辑。
二、 安装与使用
从官网获取,注意版本的支持,为了便于访问,解压缩到工作站的访问根目录下。
使用步骤:
创建相应的文件夹,一般在smarty的解压目录下,创建一个templates目录,用于存放模板,创建一个templates_c,作为编译目录。
在创建的目录的同级目录中,新建一个php文件,如index.php
<?php
//1,引入smarty类
include "libs/Smarty.class.php";
//2,实例化对象
$smarty = new Smarty();
//3,设置相关属性,设置创建的目录
$smarty->template_dir = "templates";//模板目录
$smarty->compile_dir = "templates_c";//编译目录
$smarty->assign('title', 'smarty模板');
$smarty->assign('content', 'smarty模板好用');
//5,调用display方法载入模板
$smarty->display('index.html');
编写模板文件
在complates目录创建一个index.html文件。
<!DOCTYPE HTML>
<html>
<head>{$title}</head>
<body>
{$title}
{$content}
</body>
</html>
然后访问这个index.html,就会在templates_c目录下产生编译文件,内容大致为:
<!DOCTYPE HTML>
<html>
<head><?php echo$_smarty_tpl->tpl_vars['title']->value;?>
</head>
<body>
<?php echo $_smarty_tpl->tpl_vars['title']->value;?>
<?php echo $_smarty_tpl->tpl_vars['content']->value;?>
</body>
</html><?php }
}
?>
三、 Smarty语法
(一)前端相关的语法
1. 定界符
默认的定界符是{}。
任何在定界符之外的内容,都是静态的,是不会被解析的,包括php代码;{和$中间不能有任何空格,否则将不会被解析;如果在页面中有css和js,为了防止将css或者js的内容按照smarty语法解析,需要在出现{的地方,空一格,或者不要紧贴着{;默认的定界符是可以修改的。
使用内置函数literal,解决{的冲突,比如:
<style>
h2{
color:red;
font-size:20px;
}
{literal}
.c1{color:blue;font-size:12px;}
{/literal}
</style>
也可通过修改定界符的方法,解决冲突,在index.php中,
$smarty->left_delimiter = "*";
$smarty->right_delimiter = "*";
也可以将css和js以外部方式引入,也避免冲突。
2. 注释
格式:左定界符*内容*右定界符
比如,{*xxxx*}。
3. 变量
在模板中可以使用的变量有3中来源。在php中通过assign方法分配过来的;保留变量;配置变量。
1) 通过assign分配变量
直接使用assign方法,语法,$smarty->assign(名,值)。在php中数据类型,有4种标量类型,整型、浮点型、字符串、布尔;2种复合类型,数组和对象;2种特殊类型,资源和NULL。其中,对于smarty来说,资源类型和NULL是不需要用的,对象可以用,一般不用,需要分配的类型是4种标量和数组类型。
新建一个assign.php文件,内容
<?php
//1,引入smarty类
include "libs/Smarty.class.php";
//2,实例化对象
$smarty = new Smarty();
//3,设置相关属性,设置创建的目录
$smarty->template_dir = "templates";//模板目录
$smarty->compile_dir = "templates_c";//编译目录
$smarty->assign('name', 'haha');
$smarty->assign('do', true);
$smarty->assign('age', 12);
$smarty->assign('money', 12.34);
$smarty->display('assign.tp1');
创建一个assign.tp1文件
<!DOCTYPE html>
<html>
<body>
<p>{$name}</p>
<p>{$do}</p>
<p>{$age}</p>
<p>{$money}</p>
</body>
</html>
分配数组的例子:
<?php
//1,引入smarty类
include "libs/Smarty.class.php";
//2,实例化对象
$smarty = new Smarty();
//3,设置相关属性,设置创建的目录
$smarty->template_dir = "templates";//模板目录
$smarty->compile_dir = "templates_c";//编译目录
$smarty->assign('name', 'haha');
$smarty->assign('do', true);
$smarty->assign('age', 12);
$smarty->assign('money', 12.34);
//分配数组
$smarty->assign('cont', array('hah1','hah2','哈哈3','哈哈4'));
//关联数组
$smarty->assign('user', array(
'id' => 1,
'name' =>'heihei',
'age' => 22,
'address' =>'beej',
));
$smarty->display('assign.tp1');
<!DOCTYPE html>
<html>
<body>
<p>{$name}</p>
<p>{$do}</p>
<p>{$age}</p>
<p>{$money}</p>
<ul>
<li>{$cont[0]}</li>
<li>{$cont[2]}</li>
<li>{$cont[1]}</li>
<li>{$cont[3]}</li>
<li>{$cont.3}</li>
</ul>
<ul>
<li>{$user['id']}</li>
<li>{$user['name']}</li>
<li>{$user['age']}</li>
<li>{$user['address']}</li>
<li>{$user.id}</li>
<li>{$user.name}</li>
</ul>
</body>
</html>
2) 保留变量
无需分配,直接在模板中使用,包括smarty本身以及超级全局变量。
<p>{$smarty.now}</p>
<p>{$smarty.version}</p>
<p>{$smarty.server.SERVER_NAME}</p>
定义常量
define("ROOT",getcwd());
在模板中使用常量
<p>{$smarty.const.ROOT}</p>
3) 配置变量
有的数据可以交给前端人员自定义的,比如网站的版权信息。可以用配置变量的方式。
格式:名 = 值
在smarty目录的新建一个configs目录,在这个目录下新建一个site.conf文件,配置如下:
company =haohaogan公司
num = 00010000
使用配置变量,需要载入配置,在模板中使用时,有两种方式{#名#}或者{$smarty.config.名},比如:
{config_loadfile="site.conf"}
<p>{#company#}</p>
<p>{$smarty.config.num}</p>
还可以配置段/节,比如在配置文件中
[duanwu]
color = $00ff00
[zhongqiu]
color = $0000ff
使用方式,在载入时指明使用哪个节:
{config_loadfile="site.conf" section="duanwu"}
<p>{#company#}</p>
<p>{$smarty.config.num}</p>
<p>{#color#}</p>
<hr />
4. 内置函数
页面中输出数据的时候,难免对业务逻辑的一些处理,比如需要循环输出。
1) if else
php代码
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('qq', 123);
$smarty->display('if.tp1');
模板
<body>
<h2>你的条件是{$qq}</h2>
<p class='c1'>最好的选择是
{if $qq <=50&& $qq > 30}
java
{elseif $qq <= 30&& $qq > 20}
php
{elseif $qq <= 20&& $qq > 10}
html
{else}
haha
{/if}
</p>
</body>
2) foreach
处理数组时常用foreach。
格式有两种,为:
{foreach $arrayvar as $itemvar}
{foreach $arrayvar as $keyvar->$itemvar}
一维数组的例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('user', array('haha1','hah2','哈哈3','哈哈4','哈哈'));
$smarty->display('for.tp1');
<body>
<ul>
{foreach $user as$k=>$v}
<li>{$k}---{$v}</li>
{/foreach}
</ul>
</body>
二维数组的例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('user', array('haha1','hah2','哈哈3','哈哈4','哈哈'));
$userinfo = array(
array('id'=>1,'name'=>'haha', 'sex'=>1),
array('id'=>2,'name'=>'haha2', 'sex'=>0),
array('id'=>3,'name'=>'hah3a', 'sex'=>0),
array('id'=>4,'name'=>'ha4ha', 'sex'=>1),
);
$smarty->assign('userinfo', $userinfo);
$smarty->display('for.tp1');
<tablewidth="500" border="1">
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
</tr>
<tr>
{foreach$userinfo as $k => $v}
<tr>
<td>{$v.id}</td>
<td>{$v['name']}</td>
<td>{$v.sex}</td>
</tr>
{/foreach}
</tr>
</table>
指定字段的时候,使用了两种方式。
在foreach中使用if
<tablewidth="500" border="1">
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
</tr>
<tr>
{foreach$userinfo as $k => $v}
<tr
{if$k is odd} class='odd' {/if}
>
<td>{$v.id}</td>
<td>{$v['name']}</td>
<td>{$v.sex}</td>
</tr>
{/foreach}
</tr>
</table>
Foreach的一些属性,如表:
@index |
当前数组索引,从0开始 |
@iteration |
当前循环的次数,从1开始计算 |
@first |
首次循环时,值为true |
@last |
循环到最后一次时,值为true |
@total |
总的循环次数,可在foreach内部使用,也可以在循环完成后使用 |
@show |
在foreach循环执行完之后,检测循环是否显示数据的判断 |
比如:
<tablewidth="500" border="1">
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
</tr>
<tr>
{foreach$userinfo as $k => $v}
<tr
{if$v@iteration is odd} class='odd' {/if}
>
<td>{$v.id}</td>
<td>{$v['name']}</td>
<td>{$v.sex}</td>
</tr>
{/foreach}
</tr>
</table>
3) section
用于遍历数组,但是只能遍历数字连续的索引数组。
例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('user', array('haha1','hah2','哈哈3','哈哈4','哈哈'));
$smarty->display('section.tp1');
<body>
<ul>
{section name ='index' loop = '4'}
<li>{$user[index]}</li>
{/section}
</ul>
</body>
不可以用section来遍历关联数组。如果loop=$数组名,就是遍历整个数组。比如,loop=$user。
5. 变量修饰器
有时候,在模板中使用数据,还需要做进一步的处理,而且只能在模板层面来处理。比如,在完成无限分类的展示的时候,按照层级来进行显示。显示效果不直观,需要进一步处理。对此,可以使用变量修饰器,也称为变量调节器。Smarty提供的变量修饰器很多。比如:
<p>{$smarty.now}</p>
<p>{$smarty.now|date_format:'%Y-%m-%d%H:%M:%S'}</p>
例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('haha', '哈aa哈bb哈哈哈,嘿嘿嘿嘿嘿嘿,呵呵呵呵hhheee');
$smarty->display('modifer.tp1');
<!DOCTYPE HTML>
<html>
<head>
<style>
.odd{
background-color:grey;
}
</style>
</head>
<body>
<p>{$smarty.now}</p>
<p>{$smarty.now|date_format:'%Y-%m-%d%H:%M:%S'}</p>
<hr />
<p>{$haha}</p>
<p>{$haha|truncate:10:'***'|upper}</p>
</body>
</html>
指定输出的次数,比如5次。
$smarty->assign('times',5);
<body>
<p>{$smarty.now}</p>
<p>{$smarty.now|date_format:'%Y-%m-%d%H:%M:%S'}</p>
<hr />
<p>{$haha}</p>
<p>{$haha|truncate:10:'***'|upper}</p>
<p>{'hello'|str_repeat:$times}</p>
</body>
6. 函数插件
Smarty自带了一些自定义的函数插件,可以在模板中使用,常见的有单选框、复选框、下拉列表、cycle等。
1) 单选框
例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('user', array('u1', 'u2', 'u3', 'u4'));
$smarty->assign('user2', array(
'0' => 'u1',
'1' => 'u2',
'2' => 'u3',
'3' => 'u4',
));
$smarty->display('radio.tp1');
<!DOCTYPE HTML>
<html>
<head>
<style>
.odd{
background-color:grey;
}
</style>
</head>
<body>
<p>请选择</p>
{html_radiOS name='user' values=$useroutput=$user selected='u1'}
<hr />
{html_radios name='user2'options=$user2 selected='2'}
<hr />
{html_radios name='user3'options=$user selected='3'}
</body>
</html>
2) 复选框
例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('user', array('u1', 'u2', 'u3', 'u4'));
$smarty->assign('selected', array('u1', 'u3'));
$smarty->display('checkbox.tp1');
<!DOCTYPE HTML>
<html>
<head>
<style>
.odd{
background-color:grey;
}
</style>
</head>
<body>
<p>请选择</p>
{html_checkboxesname='user[]' values=$user output=$user selected=$selected}
<hr />
{html_checkboxesname='user[]' values=$user options=$user selected='1'}
<hr />
</body>
</html>
3) 下拉列表
例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('user', array('u1', 'u2', 'u3', 'u4'));
$smarty->assign('selected', array('u1', 'u3'));
$smarty->display('select.tp1');
<!DOCTYPE HTML>
<html>
<head>
<style>
.odd{
background-color:grey;
}
</style>
</head>
<body>
<p>请选择</p>
{html_options name='user'values=$user output=$user selected='u1'}
<hr />
{html_options name='user'values=$user options=$user selected='1'}
<hr />
</body>
</html>
4) cycle
例子:
<?php
//引入smarty
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('user', array('u1', 'u2', 'u3', 'u4'));
$userinfo = array(
array('id'=>1,'name'=>'haha', 'sex'=>1),
array('id'=>2,'name'=>'haha2', 'sex'=>0),
array('id'=>3,'name'=>'hah3a', 'sex'=>0),
array('id'=>4,'name'=>'ha4ha', 'sex'=>1),
);
$smarty->assign('userinfo', $userinfo);
$smarty->display('cycle.tp1');
<!DOCTYPE HTML>
<html>
<head>
<style>
.odd{
background-color:grey;
}
</style>
</head>
<body>
<tablewidth="500" border="1">
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
</tr>
<tr>
{foreach$userinfo as $k => $v}
<tr
{if$k is odd} class='odd' {/if}
>
<td>{$v.id}</td>
<td>{$v['name']}</td>
<td>{$v.sex}</td>
</tr>
{/foreach}
</tr>
</table>
<hr />
<tablewidth="500" border="1">
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
</tr>
<tr>
{foreach$userinfo as $k => $v}
<trclass= "{cycle values = 'odd,even'}">
<td>{$v.id}</td>
<td>{$v['name']}</td>
<td>{$v.sex}</td>
</tr>
{/foreach}
</tr>
</table>
</body>
</html>
(二)php开发相关的smarty使用
1. 在项目中引入smarty
放到framework目录或者APPlication目录中都可以。如果放到framework,就是把smarty作为框架的一部分,thinkphp。如果放到application中,就是将smarty作为第三方文件引入,比如CI框架。
以作为第三方引入,在application目录下新建third_party目录,将smarty目录中的libs目录拷贝到这个目录下,并重命名为smarty。
然后在首页中载入smarty类,在视图目录中创建模板目录和编译目录,将视图文件转移到templates目录下,比如:
在主页修改代码,载入smarty,和使用smarty显示
//index方法
public functionindexAction(){
//获取所有的商品分类
$categoryModel = newCategoryModel('category');
$cats =$categoryModel->frontCats();
//echo"<pre>";
//var_dump($cats);die;
//获取推荐商品
$goodsModel = newGoodsModel('goods');
$bestGoods =$goodsModel->getBestGoods();
//载入smarty类
include APP_PATH ."third_party/smarty/Smarty.class.php";
//实例化smarty类
$smarty = newSmarty;
//设置模板目录和编译目录
$smarty->template_dir= CUR_VIEW_PATH . "templates";
$smarty->compile_dir= CUR_VIEW_PATH . "templates_c";
//分配数据
$smarty->assign('cats',$cats);
$smarty->assign('bestGoods',$bestGoods);
//载入视图
$smarty->display('index.html');
//includeCUR_VIEW_PATH . 'index.html';
}
然后在,在显示页面,使用smarty的语法获取数据,比如:
{foreach $cats as $k => $v}
<!-- <?php if ($k< 8):?> -->
{if $k < 8}
<li id="cat_1"class="">
<h3><ahref="" title="男女服装"><!-- <?php echo$v['cat_name'];?> -->{$v.cat_name}</a></h3>
<pid="cat_1_menu" class="cat_menu clearfix"style="">
<!--<?php foreach ($v['child'] as $v1):?> -->
{foreach$v.child as $v1}
<dlclass="clearfix">
<dt><ahref="女装" href=""><!-- <?php echo$v1['cat_name'];?> -->{$v1.cat_name}</a></dt>
<dd>
{foreach$v1.child as $v2}
<!--<?php foreach ($v1['child'] as $v2):?> -->
<ahref=""><!-- <?php echo $v2['cat_name'];?>-->{$v2.cat_name}</a>
{/foreach}
<!--<?php endforeach;?> -->
</dd>
</dl>
{/foreach}
<!--<?php endforeach;?> -->
</p>
</li>
{/if}
<!-- <?phpendif;?> -->
{/foreach}
<!-- <?php endforeach;?> -->
2. 改进引入,提高代码复用率
在home端创建一个Basecontroller,以供继承。
<?php
//
class BaseController extends Controller {
protected $smarty;
//构造方法
public function__construct(){
//载入smarty类
include APP_PATH ."third_party/smarty/Smarty.class.php";
//实例化smarty类
$this->smarty =new Smarty;
//设置模板目录和编译目录
$this->smarty->template_dir= CUR_VIEW_PATH . "templates";
$this->smarty->compile_dir= CUR_VIEW_PATH . "templates_c";
}
}
然后,在前端的控制器中,继承这个基础类,只需要修改分配数据和显示模板的代码就可以。
<?php
//前台首页控制器
class IndexController extends BaseController {
//index方法
public function indexAction(){
//获取所有的商品分类
$categoryModel = newCategoryModel('category');
$cats =$categoryModel->frontCats();
//echo"<pre>";
//var_dump($cats);die;
//获取推荐商品
$goodsModel = newGoodsModel('goods');
$bestGoods =$goodsModel->getBestGoods();
/*//载入smarty类
include APP_PATH ."third_party/smarty/Smarty.class.php";
//实例化smarty类
$smarty = newSmarty;
//设置模板目录和编译目录
$smarty->template_dir= CUR_VIEW_PATH . "templates";
$smarty->compile_dir= CUR_VIEW_PATH . "templates_c";*/
//分配数据
$this->smarty->assign('cats',$cats);
$this->smarty->assign('bestGoods',$bestGoods);
//载入视图
$this->smarty->display('index.html');
//includeCUR_VIEW_PATH . 'index.html';
}
}
3. 模板包含
将很多页面中都有的相同部分,比如头部信息,使用模板包含显示。
首先将头部信息,单独的保存为header.html。
然后,将公共头部中需要获取数据的功能,交给BaseController中的index方法。
{include file ='header.html'}
</p>
4. 模板继承
在比较大型的网站中,很多页面会有不止一处的内容相同的部分。使用模板的继承来实现可以达到可重用和可扩展的效果。
用法一般是定义一个父模板,定义公共的内容,通常称之为模板布局;定义一个子模板,继承自父模板,使用extends函数实现。
比如:
定义父模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<pclass="header">
头部信息
</p>
<pclass="main">
<pclass="menu">
控制面板
</p>
{block name ="content"}
<pclass="content">
具体内容
</p>
{/block}
</p>
<pclass="footer">
底部版权信息
</p>
</body>
</html>
编写调用smarty的php
<?php
//1.载入smarty类
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->display('user.tpl');
编写子模板
{extends file ='layout.tpl'}
在子模板中,需要覆盖父模板的内容,或者重新定义,可以直接声明block即可。比如:
{extends file = 'layout.tpl'}
{block name = "content"}
<pclass="content">
商品详情
</p>
{/block}
注意,在子模板中,只有extends中继承的和block中重新定义的才能显示。
使用{$smarty.block.child}布局可以调用子级的内容,{$smarty.block.parent}子级页面可以调用父级页面内容。
比如,使用一套模板,实现两种显示页面的效果。
在父模板定义嵌套的block
<body>
<pclass="header">
头部信息
</p>
{block name ="main"}
<pclass="main">
<pclass="menu">
控制面板
</p>
{block name ="content"}
<pclass="content"></p>
{/block}
</p>
{/block}
<pclass="footer">
底部版权信息
</p>
</body>
在不同的子模板中实现不同的block的内容
{extends file = 'layout.tpl'}
{block name = "content"}
<pclass="content">
商品详情
</p>
{/block}
{extends file = "layout.tpl"}
{block name = "main"}
<p class="main">
购物车
</p>
{/block}
注意,如果页面的公共部分不多,用模板包含就行,如果比较多,使用模板继承。
5. 插件扩展
在页面中输出的时候,smarty提供的变量修饰器以及php函数都不能满足,此时就需要扩展。
扩展要写在libs/plugins目录下。
例子:
<?php
//自定义变量修饰器
function smarty_modifier_mytool($string,$param) {
$string .= $param;
return $string;
}
然后调用smarty
<?php
//1.载入smarty类
include "libs/Smarty.class.php";
$smarty = new Smarty();
$smarty->template_dir = "templates";
$smarty->compile_dir = "templates_c";
$smarty->assign('text', '内容内容');
$smarty->display('mytool.tpl');
使用自定的变量修饰器
<body>
{$text|mytool:'哈哈哈'}
</body>
四、 Smarty的缓存
缓存就是将数据保存到某个硬件或者软件当中,便于快速的访问。根本上都是在内存中。常见的缓存形式有两种,数据缓存和页面缓存。
在数据库的角度看,有些数据不是经常变化的,可以把它缓存起来,以后访问的时候,可以直接访问缓存,提升效率。比如使用memcached技术。
文件缓存,也称为页面缓存。有的页面,一旦生成,就不再变化,可以将这些页面缓存起来,直接将其转成静态页面,后续的访问就是直接访问静态页面,极大提升了效率。使用页面静态化技术可以实现。
smarty也实现了缓存,实现的是文件缓存。
1. smarty缓存的使用
在基础类中设置缓存相关的内容。为了起到缓存的作用,在取数据之前,需要做一个判断,判断当前的缓存是否有效,如果有效,则无需使用模型取数据。Smarty提供了一个函数,isCached(模板名称)。
在基础类中
<?php
//
class BaseController extends Controller {
protected $smarty;
//构造方法
public function__construct(){
//载入smarty类
include APP_PATH ."third_party/smarty/Smarty.class.php";
//实例化smarty类
$this->smarty =new Smarty;
//设置模版目录和编译目录
$this->smarty->template_dir= CUR_VIEW_PATH . "templates";
$this->smarty->compile_dir= CUR_VIEW_PATH . "templates_c";
//开启缓存
$this->smarty->caching= true;
//设置缓存目录
$this->smarty->cache_dir= CUR_VIEW_PATH . "cache";
//设置缓存的有效期
$this->smarty->cache_lifetime= 60;
//开启调试模式
$this->smarty->debugging= true;
//判断缓存是否有效,如果失效则获取数据
if (!$this->smarty->isCached('index.html') ) {
$categoryModel= new CategoryModel('category');
$cats =$categoryModel->frontCats();
$this->smarty->assign('cats',$cats);
}
$this->smarty->assign('index',false);
}
}
在首页控制器类中
//index方法
public functionindexAction(){
/*//获取所有的商品分类
$categoryModel = newCategoryModel('category');
$cats =$categoryModel->frontCats();*/
//echo"<pre>";
//var_dump($cats);die;
//获取推荐商品
//判断缓存是否失效
if (!$this->smarty->isCached('index.html') ) {
$goodsModel =new GoodsModel('goods');
$bestGoods =$goodsModel->getBestGoods();
$this->smarty->assign('bestGoods',$bestGoods);
}
/*//载入smarty类
include APP_PATH ."third_party/smarty/Smarty.class.php";
//实例化smarty类
$smarty = newSmarty;
//设置模版目录和编译目录
$smarty->template_dir= CUR_VIEW_PATH . "templates";
$smarty->compile_dir= CUR_VIEW_PATH . "templates_c";*/
//分配数据
//$this->smarty->assign('cats', $cats);
$this->smarty->assign('index',true);
//载入视图
$this->smarty->display('index.html');
//includeCUR_VIEW_PATH . 'index.html';
}
缓存失效的情况,已经过了有效期的设置值,缓存文件被删除,模板文件被修改。
2. 局部不缓存
一旦页面使用了缓存,那么整个页面的内容就不会变化。实际中,在某些页面,需要动态的展示信息,比如时间,用户状态。这就需要在在页面中,有局部的内容不缓存。Smarty提供了局部不缓存的技术。
有三种方式:
标签的缓存控制,即在标签中使用nocache属性,适合于单个标签;
<body>
<p>{$smarty.now|date_format:"%Y-%m-%d%T"}</p>
<p>{$smarty.now|date_format:"%Y-%m-%d%T" nocache}</p>
</body>
变量的缓存控制,即在分配变量时设置第三个参数为true,适用于单个变量;
$smarty->assign('time', $time);
$smarty->assign('time1', $time, true);
模板区域缓存控制,即在模板页面中使用{nocache}{/nocache},适用于一块模板。
{nocache}
<p>{$smarty.now|date_format:"%Y-%m-%d%T"}</p>
<p>{$smarty.now|date_format:"%Y-%m-%d%T"}</p>
{/nocache}
3. 单模板多缓存
比如,在商品详情页,如果只是在商品控制器中设置一次判断缓存失效,然后获取数据加载数据的动作,那么在所有的商品都被定位到首次点击的的那个商品的缓存文件。所以,需要将每个商品单独的生成一个缓存文件,这就是单模板多缓存。需要在display的时候,传递第二个参数,用来标识当前的内容。比如:
public functionindexAction(){
$goods_id =$_GET['goods_id'] + 0;
if (!$this->smarty->isCached('goods.html', $goods_id) ) {
$goodsModel =new GoodsModel('goods');
$goods =$goodsModel->selectByPk($goods_id);
//var_dump($goods);die;
//分配数据
$this->smarty->assign('goods',$goods);
}
//载入视图
$this->smarty->display('goods.html',$goods_id);
}
4. 缓存组
针对需要缓存的内容中根据不同的类别,有不同的属性信息的情况,比如商品列表,服装的属性和家电的属性就不同,可以使用缓存组来达到缓存的效果。实际上是单模板多缓存的一种更为细致的方法。是一种用空间换取时间的方案。
比如:
<?php
class ListController extends BaseController {
public functionindexAction(){
$cat_id =$_GET['cat_id'] + 0;
//获取对应的数据
$size =isset($_GET['size']) ? $_GET['size'] : "";
$brand =isset($_GET['brand']) ? $_GET['brand'] : "";
$style =isset($_GET['style']) ? $_GET['style'] : "";
$material =isset($_GET['material']) ? $_GET['material'] : "";
$this->smarty->display("list.html","$size|$brand|$style|$material");
}
}
5. 删除缓存
缓存失效的情况,已经过了有效期的设置值,缓存文件被删除,模板文件被修改。一般,在后台会提供一个操作,用于清除缓存。
Smarty提供了删除缓存的方法:clearCache,删除指定模板的缓存;clearAllCache,删除所有缓存。
比如,在控制器中增加一个方法,用于清除缓存。
public functionclearAction(){
$this->smarty->clearCache('index.html');
//指定id清除
$this->smarty->clearCache('goods.html',2);
//删除所有
$this->smarty->clearAllCache();
}
五、 自定义模板引擎
1. 模板引擎原理
将php文件通过访问模板文件,如果有缓存,使用缓存中的编译文件;如果有混编文件,就访问之;如果没有,就调用smarty引擎,编译文件,将数据显示在模板文件。
2. 自定义模板引擎
基本步骤:
1) 创建目录结构
创建一个tpl目录,在这个目录下创建templates、templates_c、cache、libs4个目录和一个index.php文件。
Index.php的内容,比如:
<?php
// 载入模板类
include "libs/Template.class.php";
// 实例化模板类对象
$tpl = new Template();
//设置模板和编译目录
$tpl->template_dir = "templates";
$tpl->compile_dir = "templates_c";
//分配变量
$tpl->assign('title', '自定义模板引擎');
$tpl->assign('content', '使用自定义模板实现smarty功能');
$tpl->assign('haha', true);
$tpl->assign('user', array('us1', 'us2', 'u好','看看'));
//载入模板
$tpl->display('index.tpl');
定义一个模板文件,用于测试
<!DOCTYPE html>
<html lang="en">
<head>
<metacharset="UTF-8">
<title>Document</title>
</head>
<body>
<h3>{$title}</h3>
<p>{$content}</p>
<p>
{if $haha}
哈哈
{else}
heie
{/if}
</p>
<ul>
{foreach $user as $k=> $v}
<li>{@k}--{@v}</li>
{/foreach}
</ul>
</body>
</html>
2) 定义template类
<?php
//模板类
class Template {
//保存变量的数组属性
private $tpl_vars =array();
//模板目录
public $template_dir ="templates";
//编译目录
public $compile_dir ="templates_c";
//分配变量方法
public function assign($name,$value){
if (!empty($name)) {
$this->tpl_vars[$name]= $value;
} else {
exit('请设置变量名');
}
}
//载入模板方法
public functiondisplay($file){
//编译
$tplFile =$this->template_dir . "/{$file}";//模板文件名
$compileFile =$this->compile_dir . "/" . md5($file) . ".$file.php";//编译文件名
$content =file_get_contents($tplFile);
file_put_contents($compileFile,$content);
include$compileFile;
}
}
3) 关于正则表达式
在解析模板文件中的{}中的内容时,不管其中是变量还是控制语句时,需要能够锁定{},这就需要使用到正则表达式的知识。
正则表达式,就是用一些特定的符号和语法,来对字符串进行匹配,一般是匹配某种格式。
正则中,常用的元字符
. |
匹配除换行意外的任意字符 |
\w |
匹配字母或数字或下划线或汉字 |
\s |
匹配任意的空白符 |
\d |
匹配数字 |
\b |
匹配单词的开始或结束 |
^ |
匹配字符串的开始 |
$ |
匹配字符串的结束 |
常用的限定符
* |
重复零次或更多次 |
+ |
重复一次或更多次 |
? |
重复零次或一次 |
{n} |
重复n次 |
{n, } |
重复n次或更多次 |
{n,m} |
重复n到m次 |
比如,匹配手机号,\d{11};匹配qq,\d{5, }。
对于一些特殊字符,需要转移,使用\就可以,比如{ \{,\ \\,/ \/,$ \$。
上例中,要找到{$content},还要引用,这是反向引用。通过两步实现,捕获,将需要查找的内容放在小括号()中;引用,使用 \数字 的方式,比如\1表示第一个小括号,\2表示第二个小括号中的,类推。使用\1时需要转义,如\\1。
使用正则的时候,注意的细节,正则表达式应该放在//之间,使用单引号引用。
4) 定义parse类
<?php
//解析类
class Parse {
//解析内容
private $content;
//构造方法
public function__construct($content){
$this->content =$content;
}
//解析方法
public function parse(){
$this->parseVar();
$this->parseIf();
$this->parseFor();
return$this->content;
}
//解析普通变量
/**
* 源:{$title}{$content}
* 目标:<?php echo $this->tpl_vars['title'];?>
*/
public function parseVar(){
$pattern ='/\{\$(\w+)\s*\}/';
if(preg_match($pattern, $this->content)) {
$this->content= preg_replace($pattern, "<?php echo \$this->tpl_vars['\\1'];?>", $this->content);
}
}
//解析if语句
/*
源:{if$haha}
哈哈
{else}
heie
{/if}
目标:
<?php if($haha):?>
哈哈
<?php else :?>
heie
<?php endif;?>
*/
public function parseIf(){
$patternIf ='/\{if\s+\$(\w+)\s*\}/';
$patternEnd ='/\{\/if\s*\}/';
$patternElse ='/\{else\s*\}/';
if(preg_match($patternIf, $this->content)) {
if(preg_match($patternEnd, $this->content)) {
$this->content= preg_replace($patternIf,
"<?phpif (\$this->tpl_vars['\\1']):?>", $this->content);
$this->content= preg_replace($patternEnd, "<?php endif; ?>",$this->content);
//判断有没有else
if(preg_match($patternElse, $this->content)) {
$this->content= preg_replace($patternElse, "<?php else: ?>",$this->content);
}
} else {
exit('模板语法错误');
}
}
}
//解析foreach语句
/*
源:
{foreach $user as $k=> $v}
<li>{@k}--{@v}</li>
{/foreach}
目标:
<?php foreach($this->tpl_vars['user'] as $k => $v):?>
<li><?phpecho $k;?>--<?php echo $v;?></li?>
<?phpendforeach;?>
*/
public function parseFor(){
$patternFor ='/\{foreach\s+\$(\w+)\s+as\s+\$(\w+)\s*=>\s*\$(\w+)\s*\}/';
$patternEnd ='/\{\/foreach\s*\}/';
$patternVar ='/\{@(\w+)\s*\}/';
if(preg_match($patternFor, $this->content)) {
if(preg_match($patternEnd, $this->content)) {
$this->content= preg_replace($patternFor, "
<?phpforeach (\$this->tpl_vars['\\1'] as \$\\2 => \$\\3):?>
",$this->content);
$this->content= preg_replace($patternEnd, "<?php endforeach;?>",$this->content);
if(preg_match($patternVar, $this->content)) {
$this->content= preg_replace($patternVar, "<?php echo \$\\1;?>",$this->content);
}
}
} else {
exit('模板语法错误');
}
}
}
3. 完善template类
在temlate对目标文件进行编译前,需要进行判断,如果编译文件存在并且编译文件是有效的。判断模板文件是否被修改,如果模板文件被修改,则需要重新编译。判断文件是否被修改,可以通过文件的修改时间来判断。
正常,先有模板文件,然后才有编译文件,filemtime(模板文件)<filemtime(编译文件)。如果模板文件被修改了,那么filemtime(模板文件)>filemtime(编译文件)。
<?php
//模板类
class Template {
//保存变量的数组属性
private $tpl_vars =array();
//模板目录
public $template_dir ="templates";
//编译目录
public $compile_dir ="templates_c";
//分配变量方法
public functionassign($name, $value){
if (!empty($name)) {
$this->tpl_vars[$name]= $value;
} else {
exit('请设置变量名');
}
}
//载入模板方法
public functiondisplay($file){
//编译
$tplFile =$this->template_dir . "/{$file}";//模板文件名
$compileFile =$this->compile_dir . "/" . md5($file) . ".$file.php";//编译文件名
//如果编译文件不存在或者模板文件被修改,则重新编译
if(!file_exists($compileFile) || filemtime($tplFile) >filemtime($compileFile)) {
echo "进行编译";
//编译
$content =file_get_contents($tplFile);
//引入parse类
include"libs/Parse.class.php";
//实例化对象
$parse = newParse($content);
//调用解析方法完成解析
$content =$parse->parse();
file_put_contents($compileFile,$content);
}
//载入编译文件
include$compileFile;
}
}
4. 实现缓存
分两种情况
第一次生成缓存的过程,需要时候用ob缓冲区,开启缓冲区,生成缓存文件;
后续的访问,如果有缓存,直接访问缓存。
<?php
//模板类
class Template {
//保存变量的数组属性
private $tpl_vars =array();
//模板目录
public $template_dir ="templates";
//编译目录
public $compile_dir ="templates_c";
//设置缓存目录
public $cache_dir ="cache";
//是否开启缓存
public $caching = false;//默认不开启
//开启缓冲区
public function__construct(){
ob_start();
}
//分配变量方法
public functionassign($name, $value){
if (!empty($name)) {
$this->tpl_vars[$name]= $value;
} else {
exit('请设置变量名');
}
}
//载入模板方法
public functiondisplay($file){
//编译
$tplFile =$this->template_dir . "/{$file}";//模板文件名
$compileFile =$this->compile_dir . "/" . md5($file) . ".$file.php";//编译文件名
$cacheFile =$this->cache_dir . "/" . md5($file) . ".{$file}";//缓存文件名
//如果缓存文件存在且有效,直接访问缓存文件
if(file_exists($cacheFile) && file_exists($compileFile) &&filemtime($tplFile) <= filemtime($compileFile)) {
echo "进入缓存";
include$cacheFile;
return;
}
//如果编译文件不存在或者模板文件被修改,则重新编译
if(!file_exists($compileFile) || filemtime($tplFile) >filemtime($compileFile)) {
//echo "进行编译";
//编译
$content =file_get_contents($tplFile);
//引入parse类
include"libs/Parse.class.php";
//实例化对象
$parse = newParse($content);
//调用解析方法完成解析
$content =$parse->parse();
file_put_contents($compileFile,$content);
}
//载入编译文件
include$compileFile;
//判断是否开启缓存
if($this->caching) {
//生成缓存文件
$data =ob_get_contents();
//生成缓存文件
file_put_contents($cacheFile,$data);
ob_end_clean();
include$cacheFile;
}
}
}
六、 emmet
老名字叫做Zencoding。一款让代码书写更快的插件。
1. 用法
展开的快捷键,ctrl + E
html:xt
html:5
p
p.header
p#box
p>h2
h2+p
p>ul>li*5>a+span
input[type=’text’]
2. 安装
登陆官网下载安装。一般,高版本的sublime或者editplus都已经安装。
相关阅读
Smarty Uninstalle4 智能卸载工具 免费安装及激活教程
Smarty Uninstalle如何激活?今天小编整理了关于Smarty Uninstalle 智能卸载工具中文安装及激活教程,激活方法亲测有效,操作过程相当