标签搜索

PHP Smarty模板技术

sunshine
2022-10-12 / 0 评论 / 29 阅读
温馨提示:
本文最后更新于2022年10月12日,已超过696天没有更新,若内容或图片失效,请留言反馈。

1.1 目标

  1. 掌握Smarty模板技术的实际运用;
  2. 掌握Smarty模板技术的基础配置;
  3. 掌握常用的smarty内置函数应用;
  4. 掌握模板变量的使用以及常见的保留变量的使用;
  5. 了解smarty配置文件的使用规范;
  6. 掌握Smarty中内置函数:if分支、foreach和section循环的使用
  7. 掌握Smarty在类中引入实现子类便捷使用的方式

1.4 Smarty简介

1.4.1 Smarty的引入

1、为了分工合作,模板页面中最好不要出现PHP的代码。

2、需要将表现和内容相分离

1.2.2 Smarty介绍

1561953188908

1.5 自定义Smarty

1.3.1 演化一:(smarty生成混编文件)

在模板中不能出现PHP定界符,标准写法如下:

1、html代码

<body>
{$title}
</body>

2、PHP代码

<?php
    $title='锄禾';
    require './1-demo.html';

运行结果

1561962161195

不能解析的原因是:PHP不能识别 { 和 }

解决:

将大括号替换成PHP的定界符

1561962261095

代码实现

<?php
$title='锄禾';
$str=file_get_contents('./index.html');
$str=str_replace('{','<?php echo ',$str);    //替换左大括号
$str=str_replace('}',';?>',$str);            //替换右大括号
file_put_contents('./index.html.php', $str);    //写入混编文件
require './index.html.php';    //包含混编文件

运行

1561962843715

1.3.2 演化二:(smarty封装)

由于每个页面都要替换定界符,所以需要将替换定界符的代码封装起来

由于封装在类中,所有访问的方法需要通过面向对象的方式来访问

1561963657349

1、创建Smarty.class.php

<?php
class Smarty{
    private $tpl_var=array();
    //赋值
    public function assign($k,$v){
        $this->tpl_var[$k]=$v;
    }
    /*
    *作用:编译模板
    *@param $tpl string 模板的路径
    */
    public function compile($tpl){
        $com_file=$tpl.'.php';        //混编文件地址
        $str=file_get_contents($tpl);
        $str=str_replace('{$','<?php echo $this->tpl_var[\'',$str);    //替换左大括号
        $str=str_replace('}','\'];?>',$str);            //替换右大括号
        file_put_contents($com_file, $str);    //写入混编文件
        require $com_file;    //包含混编文件
    }
}

2、在index.php

<?php
require './Smarty.class.php';
$smarty=new Smarty();
$smarty->assign('title','锄禾');
$smarty->compile('./index.html');

小结:

1、需要将外部的变量赋值到对象的内部

2、要通过面向对象的方式访问

1.3.3 演化三:(有条件的生成混编文件)

混编文件存在并且是最新的就直接包含,否则就重新生成

模板文件修改时间<混编文件修改时间 => 混编文件是最新的

Smarty类中的代码编译代码如下

<?php
class Smarty{
    private $tpl_var=array();
    //赋值
    public function assign($k,$v){
        $this->tpl_var[$k]=$v;
    }
    /*
    *作用:编译模板
    *@param $tpl string 模板的路径
    */
    public function compile($tpl){
        $com_file=$tpl.'.php';        //混编文件地址
        //文件存在,并且模板文件修改时间<混编文件修改时间
        if(file_exists($com_file) && filemtime($tpl)<filemtime($com_file))
            require $com_file;
        else{
            $str=file_get_contents($tpl);
            $str=str_replace('{$','<?php echo $this->tpl_var[\'',$str);    //替换左大括号
            $str=str_replace('}','\'];?>',$str);            //替换右大括号
            file_put_contents($com_file, $str);    //写入混编文件
            require $com_file;    //包含混编文件
        }
    }
}

小结:

生成混编文件的条件

1、混编不存在

2、模板修改了, 模板文件修改时间>混编文件修改时间,说明模板修改过了。

1.3.4 演化四:文件分类存放

  1. 模板文件:view
  2. 混编文件:viewc
  3. Smarty文件:smarty.class.php

Smarty.class.php代码如下:

<?php
class Smarty{
   public $template_dir='./templates/';    //默认模板目录
   public $templatec_dir='./templates_c/';    //默认混编目录

   private $tpl_var=array();
   //赋值
   public function assign($k,$v){
       $this->tpl_var[$k]=$v;
   }
   /*
   *作用:编译模板
   *@param $tpl string 模板的名字
   */
   public function compile($tpl){
       $tpl_file=$this->template_dir.$tpl;    //拼接模板地址
       $com_file=$this->templatec_dir.$tpl.'.php';        //混编文件地址
       //文件存在,并且模板文件修改时间<混编文件修改时间
       if(file_exists($com_file) && filemtime($tpl_file)<filemtime($com_file))
           require $com_file;
       else{
           $str=file_get_contents($tpl_file);
           $str=str_replace('{$','<?php echo $this->tpl_var[\'',$str);    //替换左大括号
           $str=str_replace('}','\'];?>',$str);            //替换右大括号
           file_put_contents($com_file, $str);    //写入混编文件
           require $com_file;    //包含混编文件
       }
   }
}

index.php代码如下

<?php
require './Smarty/Smarty.class.php';
$smarty=new Smarty();
$smarty->template_dir='./view/';    //更改模板目录
$smarty->templatec_dir='./viewc/';    //更改混编目录
$smarty->assign('title','锄禾');
$smarty->compile('index.html');

1.3.5 演化五:封装编译方法

编译的方法是smarty的核心方法,核心方法一般是不可以直接调用,需要进行二次封装

smarty.class.php

<?php
class Smarty{
    ...
    public function display($tpl){
        require $this->compile($tpl);
    }
    /*
    *作用:编译模板
    *@param $tpl string 模板的名字
    */
    private function compile($tpl){
        ..
        //文件存在,并且模板文件修改时间<混编文件修改时间
        if(file_exists($com_file) && filemtime($tpl_file)<filemtime($com_file))
            return $com_file;    //返回混编地址
        else{
            $str=file_get_contents($tpl_file);
            $str=str_replace('{$','<?php echo $this->tpl_var[\'',$str);    //替换左大括号
            $str=str_replace('}','\'];?>',$str);            //替换右大括号
            file_put_contents($com_file, $str);    //写入混编文件
            return $com_file;    //返回混编地址
        }
    }
}

index.php

<?php
...
$smarty->assign('title','锄禾');
$smarty->display('index.html');    //传递文件名

1.6 官方Smarty介绍

1.6.1 smarty目录结构

www.smarty.net网站下载最新的smarty版本

1561967552187

解压

1561967604487

libs目录结构

1561967720685

需要掌握的smarty的属性和方法

public $left_delimiter = "{";        //左界定
public $right_delimiter = "}";        //右界定
protected $template_dir = array('./templates/');    //默认模板目录
protected $compile_dir = './templates_c/';            //默认混编目录
protected $config_dir = array('./configs/');        //默认配置目录
protected $cache_dir = './cache/';                    //默认缓存目录


public function setTemplateDir(){}                    //设置模板文件夹
public function setConfigDir(){}                    //设置配置文件夹
public function setCompileDir(){}                    //设置混编文件夹
public function setCacheDir(){}                        //设置缓存文件夹

练习:

以下关于Smarty配置描述正确的是(ABCD)
    A: 使用left_delimiter属性可以修改Smarty左定界符;     
    B: 使用right_delimiter属性可以修改Smarty右定界符;     
    C: 使用setTemplateDir()方法可以重新指定默认模板工作目录;     
    D: 使用setCompileDir()方法可以重新指定默认编译文件工作目录。     

1.6.2 smarty简单的操作

1、将libs目录拷贝到站点下,改名为smarty

2、创建模板目录templates

3、创建混编目录templates_c

4、在站点下创建1-demo.php

<?php
require './Smarty/Smarty.class.php';
$smarty=new Smarty();
$smarty->assign('title','锄禾');
$smarty->left_delimiter='{{';        //更改左界定
$smarty->right_delimiter='}}';        //更改右界定
$smarty->setTemplateDir('./view/');    //设置模板目录
$smarty->setCompileDir('./viewc/');    //设置混编目录
$smarty->display('1-demo.html');

在templates下创建demo1.html

<body>
    {{$title}}
</body>

1.6.3 注释

语法:{ }

1561969175401

注意:smarty注释在源码中看不见。

思考:已知smarty的定界符是{},那么它的注释是什么?

答:{ }

1.2 变量

smarty中变量有3中,普通变量、配置变量、保留变量

1、普通变量

普通变量就是我们自己定义的变量

方法一:在PHP中定义

$smarty->assign('name','tom');

方法二:可以在模板定义

语法:{assign var='变量名' value='值'}

例如:{assign var='sex' value='男'}

简化写法:

{$sex='男'}

例题:

php代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->assign('name','tom');        //给变量赋值
$smarty->display('1-demo.html');

HTML代码

<body>
    姓名:{$name}  <br>

    {assign var='age' value=20}
    年龄:{$age}<br>

    {$add='北京'}
    地址:{$add}
</body>

运行结果

1562117254254

2、保留变量

Smarty中有一个特殊的保留变量(内置变量),类似于PHP中的所有的超全局变量、常量、时间等信息

表达式描述
{$smarty.get.name}获取get提交的name的值
{$smarty.post.name}获取post提交的name的值
{$smarty.request.name}获取get和post提交的name的值
{$smarty.cookies.name}获取cookie中的name的值
{$smarty.session.name}获取session中的name的值
{$smarty.const.name}获取常量name
{$smarty.server.DOCUMENT_ROOT}获取服务器的虚拟目录地址
{$smarty.config.name}获取配置文件中的值
{$smarty.now}时间戳
{$smarty.ldelim}获取左界定
{$smarty.rdelim}获取右界定

例题

PHP代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
define('name', '常量name');
setcookie('name','cookie的值');
$_SESSION['name']='session的值';
$smarty->display('1-demo.html');

HTML代码

<body>
get提交:{$smarty.get.name}<br>
post提交:{$smarty.post.name}<br>
request提交:{$smarty.request.name}<br>
常量:{$smarty.const.name}<br>
cookie的值:{$smarty.cookies.name}<br>
session:{$smarty.session.name}<br>
时间戳:{$smarty.now}<br>
版本号:{$smarty.version}<br>
根目录:{$smarty.server.DOCUMENT_ROOT}<br>
左界定:{$smarty.ldelim}<br>
右界定:{$smarty.rdelim}
</body>

运行结果

1562117928996

3、配置变量

从配置文件中获取变量值,配置文件默认的文件夹是configs

1、在站点下创建配置文件夹configs

2、在configs目录下创建smarty.conf文件

color='#FF0000';
size='15px';

3、PHP页面

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->display('1-demo.html');

4、HTML页面

{config_load file='smarty.conf'}   <!--引入配置文件-->
<style>
body{
    color:{#color#};
    font-size: {$smarty.config.size}
}
</style>

小结:

1、要使用配置文件中的值,首先必须引入配置文件,通过{config_load}标签引入

2、获取配置文件中的值的方法有两种

​ 第一:{#变量名#}

​ 第二:{$smarty.config.变量名}

多学一招:配置文件中的节

在配置文件中,‘[ ]’表示配置文件的段落

例题:

配置文件

color=#FF0000
size=30px
    
[spring]    # 配置文件中的段落
color=#009900;
size=20px;

[winter]
color=#000000;
size=5px;

注意:

1、全局的一定要写在节的前面

2、配置文件中[]表示节

3、配置文件中的注释是 #

HTML页面

{config_load file='smarty.conf' section='winter'}   -- 通过section引入配置文件中的段落
<style>
body{
    color:{#color#};
    font-size: {$smarty.config.size}
}
</style>

1.3 运算符

smary中的运算符是PHP是一样的。除此以外,smarty还支持如下的运算符。

运算符描述
eqequal 相等
neqnot equal 不等于
gtgreater than 大于
ltless than 小于
lteless than or equal 小于等于
gtegreat than or equal 大于等于
is even是偶数
is odd是奇数
is not even不是偶数
is not odd不是奇数
not
mod求模取余
div by被整除
is [not] div by能否被某数整除,例如:{if $smarty.get.age is div by 3}...{/if}
is [not] even by商的结果是否为偶数
is [not] odd by商的结果是否为奇数

1.4 判断

语法:

{if 条件}

{elseif 条件}

{else}

{/if}

例题:

php代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->display('1-demo.html');

html代码

<body>
{if is_numeric($smarty.get.score)}    {#判断是否是数字#}
    {if $smarty.get.score gte 90}
        A
    {elseif $smarty.get.score gte 80}
        B
    {else}
        C
    {/if}
{else}
    不是数字
{/if}

<hr>
{if $smarty.get.score is even}
    是偶数
{elseif $smarty.get.score is odd}
    是奇数
{/if}
</body>

运行结果

1562121483179

小结:在判断中是可以使用PHP的函数的

1.5 数组

smarty中访问数组的方式有两种

数组[下标]
数组.下标

PHP代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$stu=array('tom','berry');        //索引数组
$emp=array('name'=>'rose','sex'=>'女');    //关联数组
$goods=array(
    array('name'=>'手机','price'=>22),
    array('name'=>'钢笔','price'=>10)
);
$smarty->assign('stu',$stu);
$smarty->assign('emp',$emp);
$smarty->assign('goods',$goods);
$smarty->display('2-demo.html');

HTML代码

<body>
学生:{$stu[0]}-{$stu.1}  <br>
雇员:{$emp['name']}-{$emp.sex}<br>
商品:
<ul>
    <li>{$goods[0]['name']}</li>
    <li>{$goods[0].price}</li>
    <li>{$goods.1['name']}</li>
    <li>{$goods.1.price}</li>
</ul>
</body>

运行结果

1562121978495

1.6 循环

smarty中支持的循环有:{for}、{while}、{foreach}、{section}。对于开发来说用的最多就是{foreach}循环

1.6.1 for

语法:

{for 初始值 to 结束值 [step 步长]}

{/for}
 默认步长是1

例题

<body>
{for $i=1 to 5}
    {$i}:锄禾日当午<br>
{/for}
<hr>
{for $i=1 to 5 step 2}
    {$i}:锄禾日当午<br>
{/for}
</body>

运行结果

1562122930604

1.6.2 while

语法

{while 条件}

{/while}

例题(输出5句):

<body>
{$i=1}
{while $i<=5}
    {$i++}:锄禾日当午<br>
{/while}
</body>

1.6.3 foreach

既能遍历关联数组也能遍历索引数组

语法:

{foreach 数组 as $k=>$v}

{foreachelse}
    没有数组输出
{/foreach}

foreach的属性

@index:从0开始的索引
@iteration:从1开始的编号
@first:是否是第一个元素
@last:是否是最后一个元素

PHP代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->assign('stu',array('first'=>'tom','second'=>'berry','third'=>'ketty','forth'=>'rose'));
$smarty->display('3-demo.html');

html代码

<table border='1' bordercolor='#000' width='780'>
    <tr>
        <th>是否是第一个元素</th>
        <th>索引</th>
        <th>编号</th>
        <th>键</th>
        <th>值</th>
        <th>是否是最后一个元素</th>
    </tr>
    {foreach $stu as $k=>$v}
    <tr>
        <td>{$v@first}</td>
        <td>{$v@index}</td>
        <td>{$v@iteration}</td>
        <td>{$k}</td>
        <td>{$v}</td>
        <td>{$v@last}</td>
    </tr>
    {foreachelse}
        没有输出
    {/foreach}
</table>

运行结果

1562124457735

1.6.4 section

section不支持关联数组,只能遍历索引数组

语法:

{section name=自定义名字 loop=数组}
{/section}

例题:

php

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->assign('stu',array('tom','berry'));
$smarty->display('4-demo.html');

html代码

<table border='1' bordercolor='#000' width='780'>
<tr>
    <th>是否是第一个元素</th>
    <th>索引</th>
    <th>编号</th>
    <th>值</th>
    <th>是否是最后一个元素</th>
</tr>
{section name=s loop=$stu}
<tr>
    <td>{$smarty.section.s.first}</td>
    <td>{$smarty.section.s.index}</td>
    <td>{$smarty.section.s.iteration}</td>
    <td>{$stu[s]}</td>
    <td>{$smarty.section.s.last}</td>
</tr>
{sectionelse}
    没有输出
{/section}
</table>

1562125165784

1.7 函数

函数有两种,自定义函数和内置函数

smarty的内置函数就是封装的PHP的关键字

1562125393895

1.8 变量修饰器

1.8.1 变量修饰器

变量修饰器的本质就是PHP函数,用来转换数据

php代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->display('5-demo.html');

html代码

<body>
转成大写:{'abc'|upper} <br>
转成小写:{'ABC'|lower} <br>
默认值:{$add|default:'地址不详'}<br>
去除标签:{'<b>你好吗</b>'|strip_tags}<br>
实体转换:{'<b>你好吗</b>'|escape}<br>
日期:{$smarty.now|date_format:'%Y-%m-%d %H:%M:%S'}
多个管道连续使用:{'<b>boy</b>'|strip_tags|upper}<br>
</body>

运行结果

1562126429832

注意:

1、将PHP的关键字或函数封装成标签称为函数,将PHP关键字封装成smarty关键字称为修饰器。内部的本质都是、PHP函数或PHP关键字。

2、|称为管道运算符,将前面的参数传递后后面的修饰器使用

1.8.2 自定义变量修饰器

变量修饰器存放在plugins目录中

规则:

  1. 文件的命名规则:modifier.变量修饰器名称.php
  2. 文件内方法命名规则:smarty_modifier_变量修饰器名称(形参...){}

例题

1、在plugins目录中创建modifier.cal.php页面

<?php
function smarty_modifier_cal($num1,$num2,$num3){
    return $num1+$num2+$num3;
}

2、在模板中调用

{10|cal:20:30}

10作为第一个参数传递
参数之间用冒号分隔

1.9 避免Smarty解析

smarty的定界符和css、js中的大括号产生冲突的时候,css、js中的大括号不要被smarty解析

方法一:更换定界符

方法二:左大括号后面添加空白字符

方法三:{literal} {/literal}

smarty不解析{literal} {/literal}中的内容

<style>
{literal}
body{color: #FF0000;}
{/literal}
</style>

1.10 缓存

缓存:页面缓存、空间缓存、数据缓存。smarty中的缓存就是页面缓存

smarty的缓存是页面缓存。

1.10. 1 开启缓存

$smarty->caching=true|1;        //开启缓存

1.10.2 缓存的更新

方法一:删除缓存,系统会重新生成新的缓存文件

方法二:更新了模板文件,配置文件,缓存自动更新

方法三:过了缓存的生命周期,默认是3600秒

方法四:强制更新

PHP代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->caching=true;        //开启缓存
if(date('H')>=9)
    $smarty->force_cache=true;    //强制更新缓存
$smarty->display('6-demo.html');

1.10.3 缓存的生命周期

$smarty->cache_lifetime=-1 | 0 | N
-1:永远不过期
0:立即过期
N:有效期是N秒,默认是3600秒

PHP代码

$smarty->cache_lifetime=3;    //缓存的生命周期

1.10.4 局部不缓存

局部不缓存有两种方法

1、变量不缓存    {$变量名  nocache}
2、整个块不缓存   {nocache}   {/nocache}

代码

不缓存:{$smarty.now nocache}  <br>
不缓存:{nocache}
    {$smarty.now}<br>
{/nocache}

1.10.5 缓存分页

通过$smarty->display(模板,识别id)。通过识别id来缓存分页、集合

PHP页面

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->caching=1;
$smarty->display('7-demo.html',$_GET['pageno']);

html页面

<body>
    这是第{$smarty.get.pageno}页
</body>

运行结果

1562137760608

1.10.6 缓存集合

1555322656802

每个组合都会产生缓存

PHP代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
$smarty->caching=1;
$color=$_GET['color'];
$size=$_GET['size'];
$smarty->display('7-demo.html',"$color|$size");

HTML代码

<body>
    颜色:{$smarty.get.color}<br>
    大小:{$smarty.get.size}
</body>

运行结果

1562138211626

1562138229994

1.10.7 清除缓存

$smarty->clearCache(模板,[识别id])
$smarty->clearAllCache();   //清除所有缓存

代码

<?php
require './Smarty/smarty.class.php';
$smarty=new Smarty();
//$smarty->clearCache('7-demo.html',1);
//$smarty->clearCache('7-demo.html','red|10');
//$smarty->clearCache('7-demo.html');
$smarty->clearAllCache();    //清除所有缓存

1.11 将smarty集成到项目中

1、将smarty拷贝到Lib目录下

1562139749261

2、实现smarty类的自动加载

 private static function initAutoLoad(){
        spl_autoload_register(function($class_name){
            //Smarty类存储不规则,所以将类名和地址做一个映射
            $map=array(
                'Smarty'    =>  LIB_PATH.'Smarty'.DS.'Smarty.class.php'
            );
            
           ...
            elseif(isset($map[$class_name]))
                $path=$map[$class_name];
            else   //控制器
                $path=__URL__.$class_name.'.class.php'; 
            if(file_exists($path) && is_file($path))
                require $path;
        });
    }

3、创建混编目录,并且定义混编目录地址

1562140844265

private static function initRoutes(){
  ...
    define('__VIEW__',VIEW_PATH.$p.DS);     //当前视图的目录地址
    define('__VIEWC__', APP_PATH.'Viewc'.DS.$p.DS); //混编目录
}

4、由于前后台都要启动模板,所以应该在基础控制器中实例化smarty

<?php
//基础控制器
namespace Core;
class Controller{
    protected $smarty;
    use \Traits\Jump;
    
    public function __construct() {
        $this->initSession();
        $this->initSmarty();
    }
    //初始化session
    private function initSession(){
        new \Lib\Session();
    }
    //初始化Smarty
    private function initSmarty(){
        $this->smarty=new \Smarty();
        $this->smarty->setTemplateDir(__VIEW__);   //设置模板目录
        $this->smarty->setCompileDir(__VIEWC__);    //设置混编目录
    }
}

5、在控制器中使用smarty

class ProductsController extends BaseController{
    //获取商品列表
    public function listAction() {
        //实例化模型
        $model=new \Model\ProductsModel();
        $list=$model->select();
        //加载视图
        //require __VIEW__.'products_list.html';
        $this->smarty->assign('list',$list);
        $this->smarty->display('products_list.html');
    }

6、在模板中更改如下:

{foreach $list as $rows}
<tr>
        <td>{$rows['proID']}</td>
        <td>{$rows['proname']}</td>
        <td>{$rows['proprice']}</td>
        <td><a href="index.php?p=Admin&c=Products&a=edit&proid={$rows['proID']}">修改</a></td>
        <td><a href="javascript:void(0)" onclick="if(confirm('确定要删除吗')){ location.href='index.php?p=Admin&c=Products&a=del&proid={$rows['proID']}'}">删除</a></td>
</tr>
{/foreach}
感觉很棒,欢迎点赞 OR 打赏~
1
分享到:

评论 (0)

取消