资讯专栏INFORMATION COLUMN

PHP_Smarty

printempw / 680人阅读

摘要:体现了业务与显示的分离,尽量分离。就负责判断条件,并取出数据来。显示的工作尽量靠前页面缓存缓存,重要概念。减轻了数据库的压力。控制局部不缓存在标签中控制,该标签不缓存。模板调用特殊方法使用对象注册的方式来解决。文件命名函数名定

模板

数据与表现层的标签分离

smarty是PHP 与 HTML代码的分离

小型模板类

$smarty 的工作流程:

把需要显示的全局变量,赋值塞到对象内部的属性上,一个数组中.

编译模板,把{$标签},解析成相应的代码

引入编译后的PHP文件

使用smarty的步骤:

smarty是一个类,要使用,需要先引入并实例化

assign赋值

display --> 编译到输出

smarty缺点:

编译模板,需要消耗时间

要把变量再重新赋值一份(又倒腾一次,放在对象的属性上)

</>复制代码

  1. PHP文件
  2. * 区分 模板文件和 PHP文件,把模板和编译后的结果,放置在不同的目录中.
  3. * 用2个不同的属性来记录 不同的目录
  4. */
  5. class Tmp {
  6. public $template_dir = ""; // 模版文件所在的路径
  7. public $compile_dir = ""; // 模板编译后存在的路径
  8. public $tpl_var = array(); // 接受外部的变量
  9. /**
  10. * 存储全局变量
  11. * @param {String} $key 变量名
  12. * @param {Mixin} $val 变量值
  13. */
  14. public function assign( $key, $val ) {
  15. $this->tpl_var[$key] = $val;
  16. }
  17. /**
  18. * 调用 compile模板,和自动引入
  19. * @param {String} $template 模板文件名
  20. */
  21. public function display( $template ) {
  22. $comp = $this->compile($template);
  23. include($comp);
  24. }
  25. /**
  26. * 编译
  27. * @param {String} $template 模板文件名 (需要编译的模板文件的文件名)
  28. * @return {String} $comp 编译后的文件路径
  29. *
  30. * 把指定的模板内容读取,再编译成PHP文件
  31. *
  32. * 最终外部执行的是,编译后的文件
  33. */
  34. public function compile( $template ) {
  35. // 读取模板内容
  36. $tmp = $this->template_dir . "/" . $template;
  37. $scoure = file_get_contents($tmp);
  38. // 替换模板内容
  39. $scoure = str_replace("{$", "tpl_var["", $scoure);
  40. $scoure = str_replace("}", ""];?>", $scoure);
  41. // 把编译后的内容保存成编译后的文件
  42. $comp = $this->compile_dir . "/". $template . ".php";
  43. // 判断模板是否已经存在, 加上通过 文件修改的时间来判断,模板是否已经被修改过
  44. if ( file_exists($comp) && filemtime($tmp) < filemtime($comp) ) {
  45. return $comp;
  46. }
  47. file_put_contents($comp, $scoure);
  48. return $comp;
  49. }
  50. }
  51. ?>
引入赋值和标签语法

smarty典型使用流程

</>复制代码

  1. template_dir = "./templates";
  2. $smarty->compile_dir = "./compile";
  3. // 赋值
  4. $smarty->assign("title", "T");
  5. $smarty->assign("content", "C");
  6. // 编译
  7. $smarty->display("temp01.html");
  8. ?>

smarty可以赋值为数值,数字等值,可以是数组.

VIEW:

</>复制代码

  1. 姓名:{$name}
    年龄{$age}
    兵器{$weapon}
  2. 姓名:{$zf.name}
    年龄{$zf.age}
    兵器{$zf.weapon}
  3. 姓名:{$guanyu[0]}
    年龄{$guanyu[1]}
    兵器{$guanyu[2]}

Controller

</>复制代码

  1. template_dir = "./templates";
  2. $smarty->compile_dir = "./compile";
  3. $user = array(
  4. "name" => "刘备",
  5. "age" => 28,
  6. "weapon" => "双剑"
  7. );
  8. // 赋值
  9. $smarty->assign($user);
  10. $zf = array(
  11. "name" => "张飞",
  12. "age" => 25,
  13. "weapon" => "矛"
  14. );
  15. $smarty->assign("zf", $zf);
  16. $guanyu = array("关羽", 25, "青龙");
  17. $smarty->assign("guanyu", $guanyu);
  18. // 编译
  19. $smarty->display("liubei.html");
  20. ?>

</>复制代码

  1. smarty模板标签与css标签防止冲突

如果smarty默认定界符 {} 与 css {} 冲突
可以使用以下二种方法解决

修改smarty默认定界符{{}}

也可以用{literal}{/literal}标签,来告诉smarty,此处照常输出,不用解析

</>复制代码

  1. // 配置smarty的左右定界符
  2. $smarty->left_delimiter = "{{";
  3. $smarty->right_delimiter = "}}";

</>复制代码

模板变量来源

smarty标签变量的来源:
在模板中,{$title},则说明$title标签在被assign赋过值。

</>复制代码

  1. smarty的标签变量对应的来源,除了assign,还有那些?

PHP中assign分配变量

smarty的系统保留变量

从配置文件读取到的配置变量

</>复制代码

  1. assign

</>复制代码

  1. // 引入
  2. require("../smarty3/libs/Smarty.class.php");
  3. // 实例化
  4. $smarty = new Smarty();
  5. // 配置
  6. $smarty->template_dir = "./templates";
  7. $smarty->compile_dir = "./compile";
  8. // assign 赋值
  9. $smarty->assign("name", "罗隐");
  10. $smarty->assign("poem", "我未成名君未嫁,可能俱是不如人");
  11. // 编译
  12. $smarty->display("shiju.html");

</>复制代码

  1. 系统保留变量

系统保留变量,不用赋值,能够自动获取

</>复制代码

  1. {$smarty.get.id}

$smarty.开头的标签,当成系统变量来解析,如:$smarty.get.id解析成

还有以下几个系统保留变量:

$smarty.post

$smarty.session

$smarty.cookies

常量如何显示:
$smarty.const.常量名

</>复制代码

  1. {$smarty.const.HEI}

</>复制代码

  1. 配置文件读取配置变量

注意:

配置文件,一般以.conf做后缀

配置文件的写法是:选项=值

配置smarty的config_dir,并把配置文件放在该目录下.

配置文件:

</>复制代码

  1. site=pink
  2. tel="13164889431"

获取配置文件中的变量:

</>复制代码

  1. // 引入:
  2. {config_load file="site.conf"}
  3. // 显示
  4. {$smarty.config.site}
  5. {#tel#}
append

连着往某个标签赋值多个值,可以使用append

赋值:

</>复制代码

  1. $smarty->append("color", "tan"); // _tpl_vars["color"][] = "tan"
  2. $smarty->append("color", "pink"); // _tpl_vars["color"][] = "pink"

使用:

</>复制代码

  1. {$color[0]}

  2. {$color[1]}

源码:

</>复制代码

  1. $data->tpl_vars[ $tpl_var ]->value[] = $value;

把一个值压入一个数组

</>复制代码

  1. smarty赋值时还能够引用赋值

</>复制代码

  1. assignByRef("title", $title); // _tpl_vars["title"] = &title; // 引用赋值

这个功能在PHP5以后,意义不大,PHP5以后是写时赋值

对象赋值和引用

对象赋值

</>复制代码

  1. class Human {
  2. public $name = "zf";
  3. public $age = 23;
  4. public function say() {
  5. return "HELLO WORLD";
  6. }
  7. }
  8. $man = new Human();
  9. $smarty->assign("man", $man);

显示:

</>复制代码

  1. {$man->name}
  2. {$man->age}
  3. {$man->say()}

模板的作用:分离PHP代码,让代码简洁,所以模板中的标签,应该尽量的只负责变量的输出.不要负责太多的逻辑判断,函数调用等.

简化模板配置

通过继承来简化模板配置

</>复制代码

  1. setTemplateDir("./templates"); // 模板文件位置
  2. $this->setCompileDir("./compile"); // 编译文件位置
  3. $this->setConfigDir("./conf"); // 配置文件位置
  4. }
  5. }
  6. ?>
标签数学运算

</>复制代码

  1. {$age}
  2. {$age + 2}
  3. 年纪差为:{$age - $diffAge}
逻辑判断

IF标签要成对

</>复制代码

  1. {if $price < 10000 }
  2. {$color}
  3. {else}
  4. TAN
  5. {/if}

</>复制代码

  1. {if $smarty.get.today == 0 || $smarty.get.today == 7}
  2. 周日
  3. {elseif $smarty.get.today == 6}
  4. 周六
  5. {else}
  6. 工作日
  7. {/if}

在模板中使用逻辑判断的思考:
从分工角度看:模板只负责输出 ,不负责逻辑判断。
为什么还需要有逻辑判断? 在模板上进行逻辑判断,可以极大的简化工作.

smarty循环 for循环

for循环基本应用

赋值:

</>复制代码

  1. $smarty->assign("start", 1);
  2. $smarty->assign("end", 9);

显示:

</>复制代码

  1. {for $i = $start to $end}
  2. {$i}
  3. {if $i % 3 == 0}

  4. {/if}
  5. {/for}

</>复制代码

  1. 1-100所有的奇数

  2. {for $i=$start to 100}
  3. {if $i % 2 != 0 }
  4. {$i}
  5. {/if}
  6. {/for}

</>复制代码

  1. 循环总次数$i@total,循环索引$i@iteration

</>复制代码

  1. 步长属性 控制

  2. {for $i=$start to 100 step 2}
  3. {if $i@first == $start}
  4. {$i}
  5. {elseif $i@last == $i@total}
  6. {$i}
  7. {else}
  8. {$i}
  9. {/if}
  10. {if $i@iteration % 3 == 0}

  11. {/if}
  12. {/for}
  13. 循环总次数:{$i@total}
  14. 循环索引:$i@iteration
  15. 循环的第一次:$i@first
  16. 循环的最后一次:$i@last
foreach循环

foreach循环
典型场景,二维数组的循环
例如:新闻列表,会员列表,商品列表

赋值数据

</>复制代码

  1. assign($category);
  2. $smarty->display("foreach.html");
  3. ?>

使用foreach:

</>复制代码

  1. 商品栏目

  2. // {foreach from=$category key=key item=$g}
  3. {foreach $category as $k=>$g}
  4. {/foreach}
  5. 序号栏目名栏目信息
    {$g.cat_id}{$g.cat_name}{$g.intro}

</>复制代码

  1. 循环总次数$i@total,循环索引$i@iteration

</>复制代码

  1. 商品栏目

  2. {foreach $category as $k=>$g}
  3. {/foreach}
  4. 序号栏目名栏目信息
    {$g@iteration}{$g.cat_name} {$g.intro}
  5. 索引:$g@iteration
  6. 首行:$g@first
  7. 尾行:$g@last
  8. 总条数:{$g@total}
变量调节器

变量调节器:在模板中,修改变量的显示形式的一种功能.
变量调节器的本质是一个函数,这个函数,以标签对应的变量值为参数,然后运算,把返回值,显示在标签处.

内置变量调节器:

</>复制代码

  1. capitalize [首字符大写]
  2. count_characters [字符计数]
  3. cat [连接字符串]
  4. count_paragraphs [计算段数]
  5. count_sentences [计算句数]
  6. count_words [计算词数]
  7. date_format [格式化日期]
  8. default [默认值]
  9. escape [编码]
  10. indent [缩进]
  11. lower [小写]
  12. nl2br [换行符替换成
    ]
  13. regex_replace [正则替换]
  14. replace [替换]
  15. spacify [插空]
  16. string_format [字符串格式化]
  17. strip [去除(多余空格)]
  18. strip_tags [去除html标签]
  19. truncate [截取]
  20. upper [大写]
  21. wordwrap [行宽约束]

使用变量调节器:

</>复制代码

  1. {foreach $goods as $key=>$g}
  2. {$g.goods_id}
  3. {$g.goods_name|truncate:15:"..."}
  4. {$g.shop_price}
  5. {$g.add_time|date_format:"%Y-%m-%d %H:%M:%S"}
  6. {/foreach}

调节器的功能,在PHP中也能实现,也可以在模板中进行。比较合适在模板中进行。
体现了业务与显示的分离,尽量分离。

PHP就负责判断条件,并取出数据来。
至于显示的操作,应该尽量往"前"移(越接近用户).
MySQL-->PHP-->模板-->JavaScript

合适在MySQL存储原始数据,PHP中处理.
后台的数据尽量“原始”,不要带有样式,格式。显示的工作尽量靠前.

页面缓存

缓存,smarty重要概念。
缓存:把页面内容保存在磁盘上,下次访问相同页面,直接返回保存内容。减轻了数据库的压力。

smarty缓存的用法:

开启

配置缓存的生命周期

判断是否缓存成功并是否从数据库取出数据

输出

</>复制代码

  1. // 开启缓存
  2. $smarty->caching = true;
  3. // 设置缓存生命周期
  4. $smarty->cache_lifetime = 3600;
  5. // 缓存的文件目录,用户存储缓存文件
  6. $smarty->cache_dir = "./cache";
  7. if ( !$smarty->isCached("cache.html") ) { // 判断文件是否缓存
  8. // 链接数据库
  9. $conn = mysql_connect("127.0.0.1", "root", "");
  10. // 设置字符集
  11. mysql_query("set names utf8", $conn);
  12. // 选择数据库
  13. mysql_query("use boolshop", $conn);
  14. // 查询数据
  15. $sql = "select goods_id, goods_name, shop_price, add_time from goods limit 5";
  16. $result = mysql_query($sql, $conn);
  17. $goods = array();
  18. while ( $row = mysql_fetch_assoc($result) ) {
  19. $goods[] = $row;
  20. }
  21. // 关闭数据库连接
  22. mysql_close($conn);
  23. // 赋值
  24. $smarty->assign("goods", $goods);
  25. echo "走了数据库";
  26. }
  27. $smarty->display("cache.html");
局部缓存

smarty在页面缓存的情况下,可以设置部分内容不缓存。页面中有随机广告,时间,股票信息,不适宜缓存起来。

运行的时候,还是PHP代码,没有生成静态数据。

控制局部不缓存:

在标签中控制,该标签不缓存。

</>复制代码

  1. // {$标签 nocache}
  2. {$time|date_format:"%Y-%m-%d %H:%M:%S" nocache}

控制一段标签不缓存

</>复制代码

  1. {nocache}
  2. {$time|date_format:"%Y-%m-%d %H:%M:%S"}

  3. {$time|date_format:"%Y-%m-%d %H:%M:%S"}

  4. {/nocache}

在PHP赋值时,就控制不缓存

</>复制代码

  1. $smarty->assign("time2", $time, true); // 第三个参数是 nocache,为true,说明不缓存

不缓存标签,要保证总能从PHP处得到值.

调用函数

定义函数

</>复制代码

  1. function insert_welcome( $parm ) {
  2. return "WELCOME HELLO" . ", AGE:" . $parm["age"];
  3. }

模板中使用:

</>复制代码

  1. {insert name="welcome" age=21}

单模版多缓存

场景:为商品模板设置缓存,当时从url接收的goods_id,当缓存后,所有商品都一样了,不合适。

能否为同一个模板,生成不同的缓存文件呢?
比如:根据ID的不同,来生成各个商品的缓存页面。
可以使用:单模板多缓存,
原理:生成缓存的时候,可以再传一个缓存ID。如果ID不同,则生成缓存文件不同。

</>复制代码

  1. // 编译
  2. $smarty->display("one_page.html", $goods_id);

一般的,哪些参数要影响页面的内容,就需要把哪些参数,当成“缓存ID”。
例如:分页:page=3, 栏目:cat_id=3

多个参数影响:

</>复制代码

  1. // 编译
  2. $one_page = $goods_id + $page; // 缓存ID,根据自定义规则计算
  3. $smarty->display("one_page.html", $one_page);
  4. // 缓存判断,也需要加缓存ID
  5. if ( !$smarty->isCached("one_page".html, $one_page) ) {
  6. }

模板缓存:

</>复制代码

  1. caching = true;
  2. // 设置缓存生命周期
  3. $smarty->cache_lifetime = 10;
  4. // 缓存的文件目录,用户存储缓存文件
  5. $smarty->cache_dir = "./cache";
  6. $goods_id = $_GET["goods_id"] + 0;
  7. if ( !$smarty->isCached("one_page.html", $goods_id) ) {
  8. // 链接数据库
  9. $conn = mysql_connect("127.0.0.1", "root", "");
  10. // 设置字符集
  11. mysql_query("set names utf8", $conn);
  12. // 选择数据库
  13. mysql_query("use boolshop", $conn);
  14. // 查询数据
  15. $sql = "select goods_name, shop_price, goods_desc from goods where goods_id=" . $goods_id;
  16. $result = mysql_query($sql, $conn);
  17. $goods = mysql_fetch_assoc($result);
  18. // 关闭数据库连接
  19. mysql_close($conn);
  20. // 赋值
  21. $smarty->assign($goods);
  22. }
  23. // 编译
  24. $smarty->display("one_page.html", $goods_id);
  25. ?>
强制删除缓存

简单删除缓存.
指定模板名,不指定缓存ID,则该模板对应的缓存都会被删除.
可以通过缓存ID来控制,模板对应的指定缓存删除掉.

</>复制代码

  1. clearCache("one_page.html", $goods_id);
  2. echo "删除缓存成功";
  3. ?>

出于调试目的,临时不缓存文件

</>复制代码

  1. $smarty->force_cache = true; // 强迫文件不缓存
数据对象

作用:数据分类,添加命名空间

不使用数据对象,所有数据都存储在smarty对象中.(重名就覆盖)
数据对象:把数据分类(不同类别的数据,重名不会覆盖)

</>复制代码

  1. assign("nav", $nav_top);
  2. $smarty->assign("nav", $nav_footer); // 数据覆盖
  3. /**
  4. * smarty3引入一种新的概念,叫做数据对象。
  5. * 数据对象,就是一个装数据用的框。
  6. *
  7. * 靠2个数据对象,把2个数据对象里,各赋值一个同名的`nav`,2`nav`对象互不干扰
  8. */
  9. $smarty->display("news.html");
  10. ?>

使用数据对象,命名空间

创建数据对象$smarty->createData();

数据挂载到该数据对象上.

$smarty->dispaly();声明使用的数据

</>复制代码

  1. assign("nav", $nav_top);
  2. // $smarty->assign("nav", $nav_footer);
  3. /**
  4. * smarty3引入一种新的概念,叫做数据对象。
  5. * 数据对象,就是一个装数据用的框。
  6. *
  7. * 靠2个数据对象,把2个数据对象里,各赋值一个同名的`nav`,2`nav`对象互不干扰
  8. */
  9. // 创建一个数据对象
  10. $hdata = $smarty->createData();
  11. $fdata = $smarty->createData();
  12. // 使用数据对象
  13. $hdata->assign("nav", $nav_top);
  14. $fdata->assign("nav", $nav_footer);
  15. // display时,要声明,这次使用,哪个数据对象。
  16. $smarty->display("header.html", $hdata);
  17. $smarty->display("news.html");
  18. $smarty->display("footer.html", $fdata);
  19. ?>
对象注册

场景:在模板中,smartty标签中,允许调用对象的方法,如果方法是特殊方法,比如修改密码等方法。(模板调用特殊方法)

使用对象注册的方式来解决。

作用:允许调用的方法列表。

在View视图中:
注册对象的 变量:访问方法{zf->name}. 注意不加$,方法后不加()

</>复制代码

  1. name;
  2. }
  3. public function modPass() {
  4. return "修改密码成功";
  5. }
  6. }
  7. $zf = new User();
  8. // $smarty->assign("zf", $zf);
  9. // 对象注册
  10. $smarty->registerObject("zf", $zf, array("say")); // 第三个参数可以控制允许调用的方法.
  11. $smarty->display("objLogin.html");
  12. ?>

</>复制代码

  1. 姓名:{zf->name}

  2. 年龄:{zf->age}

  3. SAY:{zf->say}

  4. {zf->modPass}

模板继承

可以在父模板中,暂留{block name=""}{/block}

注意:

子模板第一句,先声明继承{extends file=""}

子模板的目的,只是填充父模板预留的block

父模板:

</>复制代码

  1. {block name=<span class="hljs-string">"title"</span>}父模板标题{/block}
  2. {block name="header"}{/block}

  3. {block name="footer"}{/block}

子模板1:

</>复制代码

  1. {extends file="tplExteds.html"}
  2. {block name="title"}
    • 嘻嘻哈哈
    • 嘻嘻
    • 哈哈
  3. {/block}
  4. {block name="header"}头部{/block}

子模板2:

</>复制代码

  1. {extends file="tplExted.html"}
  2. {block name="footer"}2016年最后二天{/block}
变量调节器插件开发

调节器:

</>复制代码

  1. " . $string . "";
  2. }
  3. ?>

在smarty源码的目录中,plugins, 开发。

文件命名modifier.函数名.php

定义的调节器的函数名:Smarty_modifier_modcolor

display与fetch

display() 可以看成 echo fetch();
fecth()仅仅计算出应输出的结果,但是不输出,只把结果返回。

一个PHP页面如何知道本身的输出结果: 使用缓冲区

利用fetch静态化

缓冲区的理解:

fetch是如何知道当前页面的输出内容?
输出到缓冲区,在PHP的最后,读取缓冲区,就是本页面的内容。

打开缓冲区:ob_start();
读取缓冲区:ob_get_content();
清空缓冲区:ob_clean();
读取并清空:ob_get_clenan();

静态化:缓冲区+文件写操作

</>复制代码

模板引擎特点

所有模板的共性:解析标签,解析成PHP

标签解析的分类:

最多的就是正则替换 。 例如:smarty2.X系列,quickskin

通过字符串函数来解析 例如:dede的模板类.

</>复制代码

  1. 字符串解析

</>复制代码

  1. right_length = strlen($this->right_delimiter);
  2. }
  3. protected $tags = array(); // 装载分析到的标签
  4. // 编译
  5. public function parse( $file ) {
  6. $cont = file_get_contents("./templates/" . $file);
  7. $offset = 0;
  8. // 截取第一个字符 "{"
  9. while ( $poss = strpos($cont, $this->left_delimiter, $offset) !== false ) {
  10. // 取最后字符 "}"
  11. $pose = strpos($cont, $this->right_delimiter, $poss);
  12. // 截取标签
  13. $this->tags[] = substr($cont, $poss, $pose-$poss+$this->right_length);
  14. $offset = $pose + $this->right_length;
  15. }
  16. return $this->tags;
  17. }
  18. }
  19. ?>

变量的存储分类:

最多的是通过assign,把变量再次装载到模板对象中。
如:smarty,thinkphp

只把模板解析出来,再包含模板
如:discuzd的模板,把模板解析后,只返回模板的路径,再手动包含。(省略了assign过程,速度更快,显示的粗糙暴力)

语言分类:

绝大部分PHP

C语言以扩展形式写的模板引擎(Blitz)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22213.html

相关文章

发表评论

0条评论

printempw

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<