摘要:体现了业务与显示的分离,尽量分离。就负责判断条件,并取出数据来。显示的工作尽量靠前页面缓存缓存,重要概念。减轻了数据库的压力。控制局部不缓存在标签中控制,该标签不缓存。模板调用特殊方法使用对象注册的方式来解决。文件命名函数名定
模板
数据与表现层的标签分离
smarty是PHP 与 HTML代码的分离
小型模板类$smarty 的工作流程:
把需要显示的全局变量,赋值塞到对象内部的属性上,一个数组中.
编译模板,把{$标签},解析成相应的代码
引入编译后的PHP文件
使用smarty的步骤:
smarty是一个类,要使用,需要先引入并实例化
assign赋值
display --> 编译到输出
smarty缺点:
编译模板,需要消耗时间
要把变量再重新赋值一份(又倒腾一次,放在对象的属性上)
PHP文件 * 区分 模板文件和 PHP文件,把模板和编译后的结果,放置在不同的目录中. * 用2个不同的属性来记录 不同的目录 */ class Tmp { public $template_dir = ""; // 模版文件所在的路径 public $compile_dir = ""; // 模板编译后存在的路径 public $tpl_var = array(); // 接受外部的变量 /** * 存储全局变量 * @param {String} $key 变量名 * @param {Mixin} $val 变量值 */ public function assign( $key, $val ) { $this->tpl_var[$key] = $val; } /** * 调用 compile模板,和自动引入 * @param {String} $template 模板文件名 */ public function display( $template ) { $comp = $this->compile($template); include($comp); } /** * 编译 * @param {String} $template 模板文件名 (需要编译的模板文件的文件名) * @return {String} $comp 编译后的文件路径 * * 把指定的模板内容读取,再编译成PHP文件 * * 最终外部执行的是,编译后的文件 */ public function compile( $template ) { // 读取模板内容 $tmp = $this->template_dir . "/" . $template; $scoure = file_get_contents($tmp); // 替换模板内容 $scoure = str_replace("{$", "tpl_var["", $scoure); $scoure = str_replace("}", ""];?>", $scoure); // 把编译后的内容保存成编译后的文件 $comp = $this->compile_dir . "/". $template . ".php"; // 判断模板是否已经存在, 加上通过 文件修改的时间来判断,模板是否已经被修改过 if ( file_exists($comp) && filemtime($tmp) < filemtime($comp) ) { return $comp; } file_put_contents($comp, $scoure); return $comp; } } ?>引入赋值和标签语法
smarty典型使用流程
template_dir = "./templates"; $smarty->compile_dir = "./compile"; // 赋值 $smarty->assign("title", "T"); $smarty->assign("content", "C"); // 编译 $smarty->display("temp01.html"); ?>
smarty可以赋值为数值,数字等值,可以是数组.
VIEW:
姓名: | {$name} |
年龄 | {$age} |
兵器 | {$weapon} |
姓名: | {$zf.name} |
年龄 | {$zf.age} |
兵器 | {$zf.weapon} |
姓名: | {$guanyu[0]} |
年龄 | {$guanyu[1]} |
兵器 | {$guanyu[2]} |
Controller
template_dir = "./templates"; $smarty->compile_dir = "./compile"; $user = array( "name" => "刘备", "age" => 28, "weapon" => "双剑" ); // 赋值 $smarty->assign($user); $zf = array( "name" => "张飞", "age" => 25, "weapon" => "矛" ); $smarty->assign("zf", $zf); $guanyu = array("关羽", 25, "青龙"); $smarty->assign("guanyu", $guanyu); // 编译 $smarty->display("liubei.html"); ?>
smarty模板标签与css标签防止冲突
如果smarty默认定界符 {} 与 css {} 冲突
可以使用以下二种方法解决
修改smarty默认定界符{{}}
也可以用{literal}{/literal}标签,来告诉smarty,此处照常输出,不用解析
// 配置smarty的左右定界符 $smarty->left_delimiter = "{{"; $smarty->right_delimiter = "}}";
smarty标签变量的来源:
在模板中,{$title},则说明$title标签在被assign赋过值。
smarty的标签变量对应的来源,除了assign,还有那些?
PHP中assign分配变量
smarty的系统保留变量
从配置文件读取到的配置变量
assign
// 引入 require("../smarty3/libs/Smarty.class.php"); // 实例化 $smarty = new Smarty(); // 配置 $smarty->template_dir = "./templates"; $smarty->compile_dir = "./compile"; // assign 赋值 $smarty->assign("name", "罗隐"); $smarty->assign("poem", "我未成名君未嫁,可能俱是不如人"); // 编译 $smarty->display("shiju.html");
系统保留变量
系统保留变量,不用赋值,能够自动获取
{$smarty.get.id}
$smarty.开头的标签,当成系统变量来解析,如:$smarty.get.id解析成
还有以下几个系统保留变量:
$smarty.post
$smarty.session
$smarty.cookies
常量如何显示:
$smarty.const.常量名
{$smarty.const.HEI}
配置文件读取配置变量
注意:
配置文件,一般以.conf做后缀
配置文件的写法是:选项=值
配置smarty的config_dir,并把配置文件放在该目录下.
配置文件:
site=pink tel="13164889431"
获取配置文件中的变量:
// 引入: {config_load file="site.conf"} // 显示append{$smarty.config.site}{#tel#}
连着往某个标签赋值多个值,可以使用append
赋值:
$smarty->append("color", "tan"); // _tpl_vars["color"][] = "tan" $smarty->append("color", "pink"); // _tpl_vars["color"][] = "pink"
使用:
{$color[0]}
{$color[1]}
源码:
$data->tpl_vars[ $tpl_var ]->value[] = $value;
把一个值压入一个数组
smarty赋值时还能够引用赋值
assignByRef("title", $title); // _tpl_vars["title"] = &title; // 引用赋值
这个功能在PHP5以后,意义不大,PHP5以后是写时赋值
对象赋值和引用对象赋值
class Human { public $name = "zf"; public $age = 23; public function say() { return "HELLO WORLD"; } } $man = new Human(); $smarty->assign("man", $man);
显示:
{$man->name}{$man->age}{$man->say()}
模板的作用:分离PHP代码,让代码简洁,所以模板中的标签,应该尽量的只负责变量的输出.不要负责太多的逻辑判断,函数调用等.
简化模板配置通过继承来简化模板配置
setTemplateDir("./templates"); // 模板文件位置 $this->setCompileDir("./compile"); // 编译文件位置 $this->setConfigDir("./conf"); // 配置文件位置 } } ?>标签数学运算
逻辑判断{$age}{$age + 2}年纪差为:{$age - $diffAge}
IF标签要成对
{if $price < 10000 }{$color}{else}TAN{/if}
{if $smarty.get.today == 0 || $smarty.get.today == 7}周日{elseif $smarty.get.today == 6}周六{else}工作日{/if}
在模板中使用逻辑判断的思考:
从分工角度看:模板只负责输出 ,不负责逻辑判断。
为什么还需要有逻辑判断? 在模板上进行逻辑判断,可以极大的简化工作.
for循环基本应用
赋值:
$smarty->assign("start", 1); $smarty->assign("end", 9);
显示:
{for $i = $start to $end} {$i} {if $i % 3 == 0}
{/if} {/for}
1-100所有的奇数
{for $i=$start to 100} {if $i % 2 != 0 } {$i} {/if} {/for}
循环总次数$i@total,循环索引$i@iteration
foreach循环步长属性 控制
{for $i=$start to 100 step 2} {if $i@first == $start} {$i} {elseif $i@last == $i@total} {$i} {else} {$i} {/if} {if $i@iteration % 3 == 0}
{/if} {/for}循环总次数:{$i@total}循环索引:$i@iteration循环的第一次:$i@first循环的最后一次:$i@last
foreach循环
典型场景,二维数组的循环
例如:新闻列表,会员列表,商品列表
赋值数据
assign($category); $smarty->display("foreach.html"); ?>
使用foreach:
商品栏目
序号 | 栏目名 | 栏目信息 |
{$g.cat_id} | {$g.cat_name} | {$g.intro} |
循环总次数$i@total,循环索引$i@iteration
商品栏目
序号 | 栏目名 | 栏目信息 |
{$g@iteration} | {$g.cat_name} | {$g.intro} |
变量调节器:在模板中,修改变量的显示形式的一种功能.
变量调节器的本质是一个函数,这个函数,以标签对应的变量值为参数,然后运算,把返回值,显示在标签处.
内置变量调节器:
capitalize [首字符大写] count_characters [字符计数] cat [连接字符串] count_paragraphs [计算段数] count_sentences [计算句数] count_words [计算词数] date_format [格式化日期] default [默认值] escape [编码] indent [缩进] lower [小写] nl2br [换行符替换成
] regex_replace [正则替换] replace [替换] spacify [插空] string_format [字符串格式化] strip [去除(多余空格)] strip_tags [去除html标签] truncate [截取] upper [大写] wordwrap [行宽约束]
使用变量调节器:
{foreach $goods as $key=>$g}{/foreach} {$g.goods_id} {$g.goods_name|truncate:15:"..."} {$g.shop_price} {$g.add_time|date_format:"%Y-%m-%d %H:%M:%S"}
调节器的功能,在PHP中也能实现,也可以在模板中进行。比较合适在模板中进行。
体现了业务与显示的分离,尽量分离。
PHP就负责判断条件,并取出数据来。
至于显示的操作,应该尽量往"前"移(越接近用户).
MySQL-->PHP-->模板-->JavaScript
合适在MySQL存储原始数据,PHP中处理.
后台的数据尽量“原始”,不要带有样式,格式。显示的工作尽量靠前.
缓存,smarty重要概念。
缓存:把页面内容保存在磁盘上,下次访问相同页面,直接返回保存内容。减轻了数据库的压力。
smarty缓存的用法:
开启
配置缓存的生命周期
判断是否缓存成功并是否从数据库取出数据
输出
// 开启缓存 $smarty->caching = true; // 设置缓存生命周期 $smarty->cache_lifetime = 3600; // 缓存的文件目录,用户存储缓存文件 $smarty->cache_dir = "./cache"; if ( !$smarty->isCached("cache.html") ) { // 判断文件是否缓存 // 链接数据库 $conn = mysql_connect("127.0.0.1", "root", ""); // 设置字符集 mysql_query("set names utf8", $conn); // 选择数据库 mysql_query("use boolshop", $conn); // 查询数据 $sql = "select goods_id, goods_name, shop_price, add_time from goods limit 5"; $result = mysql_query($sql, $conn); $goods = array(); while ( $row = mysql_fetch_assoc($result) ) { $goods[] = $row; } // 关闭数据库连接 mysql_close($conn); // 赋值 $smarty->assign("goods", $goods); echo "走了数据库"; } $smarty->display("cache.html");局部缓存
smarty在页面缓存的情况下,可以设置部分内容不缓存。页面中有随机广告,时间,股票信息,不适宜缓存起来。
运行的时候,还是PHP代码,没有生成静态数据。
控制局部不缓存:
在标签中控制,该标签不缓存。
// {$标签 nocache}{$time|date_format:"%Y-%m-%d %H:%M:%S" nocache}
控制一段标签不缓存
{nocache}{$time|date_format:"%Y-%m-%d %H:%M:%S"}
{$time|date_format:"%Y-%m-%d %H:%M:%S"}
{/nocache}
在PHP赋值时,就控制不缓存
$smarty->assign("time2", $time, true); // 第三个参数是 nocache,为true,说明不缓存
不缓存标签,要保证总能从PHP处得到值.
调用函数
定义函数
function insert_welcome( $parm ) { return "WELCOME HELLO" . ", AGE:" . $parm["age"]; }
模板中使用:
单模版多缓存{insert name="welcome" age=21}
场景:为商品模板设置缓存,当时从url接收的goods_id,当缓存后,所有商品都一样了,不合适。
能否为同一个模板,生成不同的缓存文件呢?
比如:根据ID的不同,来生成各个商品的缓存页面。
可以使用:单模板多缓存,
原理:生成缓存的时候,可以再传一个缓存ID。如果ID不同,则生成缓存文件不同。
// 编译 $smarty->display("one_page.html", $goods_id);
一般的,哪些参数要影响页面的内容,就需要把哪些参数,当成“缓存ID”。
例如:分页:page=3, 栏目:cat_id=3
多个参数影响:
// 编译 $one_page = $goods_id + $page; // 缓存ID,根据自定义规则计算 $smarty->display("one_page.html", $one_page); // 缓存判断,也需要加缓存ID if ( !$smarty->isCached("one_page".html, $one_page) ) { }
模板缓存:
caching = true; // 设置缓存生命周期 $smarty->cache_lifetime = 10; // 缓存的文件目录,用户存储缓存文件 $smarty->cache_dir = "./cache"; $goods_id = $_GET["goods_id"] + 0; if ( !$smarty->isCached("one_page.html", $goods_id) ) { // 链接数据库 $conn = mysql_connect("127.0.0.1", "root", ""); // 设置字符集 mysql_query("set names utf8", $conn); // 选择数据库 mysql_query("use boolshop", $conn); // 查询数据 $sql = "select goods_name, shop_price, goods_desc from goods where goods_id=" . $goods_id; $result = mysql_query($sql, $conn); $goods = mysql_fetch_assoc($result); // 关闭数据库连接 mysql_close($conn); // 赋值 $smarty->assign($goods); } // 编译 $smarty->display("one_page.html", $goods_id); ?>强制删除缓存
简单删除缓存.
指定模板名,不指定缓存ID,则该模板对应的缓存都会被删除.
可以通过缓存ID来控制,模板对应的指定缓存删除掉.
clearCache("one_page.html", $goods_id); echo "删除缓存成功"; ?>
出于调试目的,临时不缓存文件
$smarty->force_cache = true; // 强迫文件不缓存数据对象
作用:数据分类,添加命名空间
不使用数据对象,所有数据都存储在smarty对象中.(重名就覆盖)
数据对象:把数据分类(不同类别的数据,重名不会覆盖)
assign("nav", $nav_top); $smarty->assign("nav", $nav_footer); // 数据覆盖 /** * smarty3引入一种新的概念,叫做数据对象。 * 数据对象,就是一个装数据用的框。 * * 靠2个数据对象,把2个数据对象里,各赋值一个同名的`nav`,2个`nav`对象互不干扰 */ $smarty->display("news.html"); ?>
使用数据对象,命名空间
创建数据对象$smarty->createData();
数据挂载到该数据对象上.
$smarty->dispaly();声明使用的数据
assign("nav", $nav_top); // $smarty->assign("nav", $nav_footer); /** * smarty3引入一种新的概念,叫做数据对象。 * 数据对象,就是一个装数据用的框。 * * 靠2个数据对象,把2个数据对象里,各赋值一个同名的`nav`,2个`nav`对象互不干扰 */ // 创建一个数据对象 $hdata = $smarty->createData(); $fdata = $smarty->createData(); // 使用数据对象 $hdata->assign("nav", $nav_top); $fdata->assign("nav", $nav_footer); // display时,要声明,这次使用,哪个数据对象。 $smarty->display("header.html", $hdata); $smarty->display("news.html"); $smarty->display("footer.html", $fdata); ?>对象注册
场景:在模板中,smartty标签中,允许调用对象的方法,如果方法是特殊方法,比如修改密码等方法。(模板调用特殊方法)
使用对象注册的方式来解决。
作用:允许调用的方法列表。
在View视图中:
注册对象的 变量:访问方法{zf->name}. 注意不加$,方法后不加()
name; } public function modPass() { return "修改密码成功"; } } $zf = new User(); // $smarty->assign("zf", $zf); // 对象注册 $smarty->registerObject("zf", $zf, array("say")); // 第三个参数可以控制允许调用的方法. $smarty->display("objLogin.html"); ?>
模板继承姓名:{zf->name}
年龄:{zf->age}
SAY:{zf->say}
{zf->modPass}
可以在父模板中,暂留{block name=""}{/block}
注意:
子模板第一句,先声明继承{extends file=""}
子模板的目的,只是填充父模板预留的block
父模板:
{block name="title"}父模板标题{/block} {block name="header"}{/block}
{block name="footer"}{/block}
子模板1:
{extends file="tplExteds.html"} {block name="title"}
子模板2:
{extends file="tplExted.html"} {block name="footer"}2016年最后二天{/block}变量调节器插件开发
调节器:
" . $string . ""; } ?>
在smarty源码的目录中,plugins, 开发。
文件命名modifier.函数名.php
定义的调节器的函数名:Smarty_modifier_modcolor
display与fetchdisplay() 可以看成 echo fetch();
fecth()仅仅计算出应输出的结果,但是不输出,只把结果返回。
一个PHP页面如何知道本身的输出结果: 使用缓冲区。
利用fetch静态化缓冲区的理解:
fetch是如何知道当前页面的输出内容?
输出到缓冲区,在PHP的最后,读取缓冲区,就是本页面的内容。
打开缓冲区:ob_start();
读取缓冲区:ob_get_content();
清空缓冲区:ob_clean();
读取并清空:ob_get_clenan();
静态化:缓冲区+文件写操作
模板引擎特点所有模板的共性:解析标签,解析成PHP
标签解析的分类:
最多的就是正则替换 。 例如:smarty2.X系列,quickskin
通过字符串函数来解析 例如:dede的模板类.
字符串解析
right_length = strlen($this->right_delimiter); } protected $tags = array(); // 装载分析到的标签 // 编译 public function parse( $file ) { $cont = file_get_contents("./templates/" . $file); $offset = 0; // 截取第一个字符 "{" while ( $poss = strpos($cont, $this->left_delimiter, $offset) !== false ) { // 取最后字符 "}" $pose = strpos($cont, $this->right_delimiter, $poss); // 截取标签 $this->tags[] = substr($cont, $poss, $pose-$poss+$this->right_length); $offset = $pose + $this->right_length; } return $this->tags; } } ?>
变量的存储分类:
最多的是通过assign,把变量再次装载到模板对象中。
如:smarty,thinkphp
只把模板解析出来,再包含模板
如:discuzd的模板,把模板解析后,只返回模板的路径,再手动包含。(省略了assign过程,速度更快,显示的粗糙暴力)
语言分类:
绝大部分PHP
C语言以扩展形式写的模板引擎(Blitz)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/22213.html
阅读 3405·2019-08-30 15:55
阅读 2028·2019-08-30 15:44
阅读 1394·2019-08-30 12:47
阅读 703·2019-08-30 11:05
阅读 1571·2019-08-30 10:54
阅读 634·2019-08-29 16:07
阅读 3526·2019-08-29 14:17
阅读 2191·2019-08-23 18:31