首页

smarty的简单实现

kkcode
2018-03-31  阅读 137

smarty的思想

当前smarty的版本是v3.1.2 把标签解析成php输出语句,即是模板文件到php文件的过程。

smarty之辩

  • smarty编译模板浪费时间
  • 在把变量重新赋值到对象的属性上,增大了开销
  • 多引入了Smarty这个类

Smarty之简单实现


class miniSmarty {
    public $template_dir = ''; //模板文件所在的目录
    public $complete_dir = ''; //编译后文件所在目录

    // 定义一个数组,用来接收外部的变量
    public $_tpl_var = array();

    public function compile($template){
        $tempFile = $this->$template_dir . '/' . $template;
        // 读取模板文件内容
        $source = file_get_contents($tempFile);

        // 判断编译文件是否存在且模板文件修改时间小于编译后的文件的修改时间=》不用再次编译
        if(file_exists($compFile) && filemtime($tempFile)<filemtime($compFile)){
            return $compFile;
        }

        // 替换模板内容
        $source = str_replace('{$','<?php echo $this->_tpl_var[\'',$source);
        $source = str_replace('}','\'];?>',$source);

        // 再把编译后的文件保存成php文件
        $compFile = $this->$complete_dir . '/' . $template . '.php';
        file_put_contents($compFile,$source);

        return $compFile;
    }

    public fucntion assign($key,$value){
        $this->_tpl_var[$key] = $value;
    }

    public function display($template){
        $compileFile = $this->compile($template);
        include($compileFile);
    }
}
复制代码

smarty的工作流程

  1. 把需要显示的全局变量,塞到对象内部的属性上,一个数组里
  2. 编译模板即把{$标签}解析成相应的php代码
  3. 引入编译后的php文件

使用Smarty的步骤

  1. Smarty是一个类,先引入并实例化
  2. 配置:模板目录和编译目录...
  3. assign赋值
  4. 调用display方法,并把模板文件当参数传入进去
①引入smarty
require('../smarty3/smaty.class.php');
②实例化
$smarty = new Smarty();
③配置
$smarty->template_dir('../template');
$smarty->complete_dir('../complete');
④赋值
$smarty->assign('language','php');
$smarty->assign('frame','smarty3');
⑤编译模板并引入
$smarty->display('technology.html');
复制代码

待编译模板文件technology.html

<!DOCTYPE html>
<html>
<head>
    <title>{$frame}</title>
</head>
<body>
    {$language}
</body>
</html>复制代码

编译后的文件technology.php

<!DOCTYPE html>
<html>
<head>
    <title><?php echo $this->_tpl_var['frame']; ?></title>
</head>
<body>
    <?php echo $this->_tpl_var['language']; ?>
</body>
</html>复制代码

smarty assign 赋值数组

从数据库取出用户信息

require("./smarty.class.php");
$smarty = new Smarty();
$user = array("name"=>"元红娘","age"=>"7","weapon"=>"不属于当前世界的灵魂");

// ①
$smarty->assign("name",$user["name"]);
$smarty->assign("age",$user["age"]);
$smarty->assign("weapon",$user["weapon"]);

// ②
$le = array("name"=>"元灵儿","age"=>"5","weapon"=>"童心");
$smarty->assign("le",$le);

// ③
$lzy = array(0=>"梁智远",1=>"27","weapon"=>"马鞭");
$smarty->assign("$lzy",$lzy);

$smarty->display('news.html');

在news.html中,取值分别是:
① $name,$age,$weapon$le.name,$le.age,$le.weapon
③ $lzy[0],$lzy[1],$lzy.weapon
复制代码

smarty可以赋值字符串,数字等值,也可以赋值给标签一个数组。

  • 在模板里解析数组时,可以使用{$标签.key} 或者 {$标签.index}
    • 当键为字符串时,即关联数组使用 {$标签.key}
    • 当键为数字时,即索引数组使用 {$标签.key} 或者 {$标签.index}
  • 因此,全部使用 {$标签.key} 可以满足所有的情况。

smarty与js、css定界符冲突解决方法

smarty的默认定界符是{ },在使用中js、css可能与之冲突,因为smarty引擎把js中{ }之间的内容也当做smarty语句来处理

解决方法:

  1. 更改smarty定界符,{%%}。(麻烦,而且习惯了使用{})
  2. 使用{literal} {/literal}包含js、css,这样告诉smarty引擎中间代码非smarty语句
  3. 将css或js{}换行隔开
// ① 更改smarty定界符
$smarty->left-delimiter = '{%';
$smarty->right-delimiter = '%}';


// ② {literal} {/literal}
<style>
    {literal}
        table{background:pink;}
    {/literal}
</style>

// ③ 将css或js{}换行隔开
<style>
    table{
        background:pink;
    }
</style>复制代码

smarty assign深入讨论

根据smarty的源码,如果第一个参数是数组的话, 效果是把此数组的每个值赋值到以相应的键上为名称的标签上去。

$lzy = array("name"=>"梁智远","age"=>"27");
$smarty->assign($lzy);

// 相当于
$smarty->assign("name","梁智远");
$smarty->assign("age","27");复制代码

smarty模板三种变量来源

smarty标题变量对应的来源,除了assign还有什么?

答: smarty标签变量来源于三个部分。

  1. 是php中assign分配的变量
  2. smarty系统保留变量
  3. 从配置文件读取到的配置变量
// 三种变量来源之assign赋值
$smarty->assign("name","罗隐");
$smarty->assign("poem","我未成名君为家,可能俱是不如人");

// 三种变量来源之smarty系统保留变量,不用赋值,自动获取
在模板中直接取值`{$smarty.get.id}`

$smarty.开头的标签作为系统保留变量来解析
如:`{$smarty.get.id}`解析成<?php echo $_GET["id"];?>

$smarty.session,$smarty.cookies,$smarty.get,$smarty.post,$smarty.const.常量名

// 三种变量来源之从配置文件读取到的配置变量
《有些数据,比如网站底部的电话信息,不想入库,可以直接写到一个配置文件中,模板能读出配置文件的配置选项》

《
1. 配置文件一般以.conf做后缀
2. 配置文件的写法是
    *选项1 = 值1
    *选项2 = 值2
3.配置smarty的config_dir,并把配置文件放在该目录下。
在模板中载入配置文件{config_load file "site.conf" }
读取:{$smarty.config.site}
使用下面这种方式也可以读取
{#tel#}//site.conf
site: 百度
tel: '13400134000'
复制代码

smarty对象的赋值和引用

  1. smarty能赋值数组,能否赋值对象呢?
  2. 我们总是反复配置Smarty模板的template_dir等选项,能否简化?
  3. 模板里用标签引用一个变量,还能否进行修改?
  4. php中能分支,循环输出,模板中能不能?
①引入smarty
require('../smarty3/smaty.class.php');
②实例化
$smarty = new Smarty();
③配置
$smarty->template_dir('../template');
$smarty->complete_dir('../complete');

class human {
    public $name = '张三';
    public $age = '25';

    public function say(){
        return 'hello world';
    }
}

$man = new human();

$smarty->assign('man',$man);

$smarty->display('object.html');
复制代码

object.html

<!DOCTYPE html>
<html>
<head>
    <title>对象的引用是$标签->属性</title>
</head>
<body>
    <h2>{$man->name}</h2>
    <h2>{$man->age}</h2>

    <h1>调用对象的方法使用$标签->method();</h1>
    <p>{$man->name}说:{$man->say()}</p>

    所以,模板中的标签,应尽量只负责变量的 输出。
    就是负责显示数据的,不用负责太多的逻辑判断,函数调用等。
    所以,不推荐在模板中做逻辑判断及函数调用等。

</body>
</html>复制代码

通过继承来简化模板配置


// mySmarty.class.php

class MySmarty extend Smarty {

    // template_dir 和compile_dir 是父类的私有属性
    // 因此,无法复写,但是可以利用开放的接口来实现。
    public function __construct(){
        parent::__construct();

        $this->setTemplateDir('./template');
        $this->setCompileDir('./compile');
    }

}

复制代码
  • 再次使用Smarty

require('../smarty3/smaty.class.php');
require('../mySmaty.class.php');

$smarty = new MySmarty();

class human {
    public $name = '张三';
    public $age = '25';

    public function say(){
        return 'hello world';
    }
}

$man = new human();
$smarty->assign('man',$man);
$smarty->display('object.html');
复制代码
  • 参考燕十八老师的smarty视频教程,其官网地址是布尔教育
本文为作者原创文章,转载无需和我联系,但请注明转载链接。 【前端黑猫】