做一个模仿Smarty的简易模版

---恢复内容开始---

今天终于学习完了一个慕课网的正则表达式的视频,感觉挺不错的,推荐给大家

下面是我学习写的一些代码

首先要先明白什么是Smarty模版。

这种模版就是将一个文件中的代码运用正则替换为令一段代码以供下一步的运行。也就是说可以通过这个模版来省略很多语法,结构上面的规则,从而很好的将前端开发和后端开发分离,不需什么都懂,在这个山寨的模版里面主要是将前端的HTML代码中的一些字段替换成可被运行的PHP代码,完成给用户的最后的输出。

好,首先是新建的项目,既然有编译,就有个源文件和编译后存放的文件夹,如下图

在这个目录下,新建一个PHP文件,命名为template.class.php,写编译模版类

首先,定义一个类

1 class template{
2
3     private $templateDir;                        //源文件目录
4     private $compileDir;                        //编译后的文件目录
5     private $leftTag = ‘{#‘;                    //正则模式左标记
6     private $rightTag = ‘#}‘;                    //右标记
7     private $currentTemp = ‘‘;                    //正在编译的模板文件名
8     private $outputHtml;                        //存放正在编译中的模板文件中的HTML代码(存后替换输出)
9     private $varPool = array();                    //自己定义的变量池

定义一些私有属性,每个属性都在背后做了注释,其中标记并不指定,只是给个默认初始值,用户调用时还可以自己定义的

接下来写一个构造函数

public function __construct($templateDir,$compileDir,$leftTag = null, $rightTag = null){
        $this->templateDir = $templateDir;
        $this->compileDir= $compileDir;
        if(!empty($leftTag)) $this->leftTag= $leftTag;
        if(!empty($rightTag)) $this->rightTag = $rightTag;           //给出源文件目录,编译文件目录,可自己定义界定符
    }

这个构造函数用来初始化对象的一些基本属性,包括要编译的源文件目录,结果存放目录,还有正则匹配的标记等,用户可在这里定义自己想要的标记

然后写一些基础的方法,为之后的编译服务,首先是给变量池中赋值,取值

    public function assign($tag,$var){
        $this->varPool[$tag] = $var;                        //给变量池里定义变量

    }

    public function getVar($tag){
        return $this->varPool[$tag];                        //获取变量值
    }

接下来是找到要编译的源文件的目录,并获取文件内容,传给对象的基本属性outputhtml,为后续编译准备

    public function getSourceTemplate($templateName,$ext = ‘.html.‘){
        $this->currentTemp = $templateName;                              //将要编译的文件名传给对象的当前编译文件私有属性
        $sourceFilename = $this->templateDir.$this->currentTemp.$ext;    //得到完整的源文件路径
        $this->outputHtml = file_get_contents($sourceFilename);            //把文件中的内容传给对象,即对象获取文件中的代                                                                    码
    }                                                                    //这个方法用来获取模板的源文件

方法的第二个参数只是个默认值,可以修改。第一条语句是将文件名传给对象的currentTemp私有属性储存,第二条语句是连接起目标文件的完整目录。后续用一个file_get_contents函数获取内容,传给对象。

准备工作就绪,接下来是正则匹配替换方法,也是最核心的部分

                                    //最核心的方法
    public function compileTemplate($templateName = null,$ext = ‘.html‘){
        $templateName = empty($templateName)   ? $this->currentTemp :$templateName;    //先得到要编译的源文件名称,如果调用方法时没给,则使用私有属性中的文件名

        $pattern = ‘/‘.preg_quote($this->leftTag);
        $pattern.= ‘ *\$([a-zA-Z_]\w*) *‘;
        $pattern.= preg_quote($this->rightTag).‘/‘;
        $this->outputHtml = preg_replace($pattern,‘<?php echo $this->getVar(\‘$1\‘);?>‘,$this->outputHtml); //$1,匹配到的第一个子模式中的内容,\\1也可以

首先得到完整准确目录,与之前的语句相同。接着就是正则模式的书写。preg_quote是为了防止定义的标记中有正则运算符,做一个转换。‘ *‘这个是为了给予前端代码书写更多空间,允许一些无用的空格出现。子模式为要匹配到的内容,方括号里是php变量的书写规则,字母或下划线开头。

接着就使用了一个preg_replace语句开始编译,按$pattern模式将匹配到的outputHtml中的内容替换成php输入语句,‘$1‘这个是指前面正则匹配中匹配到的第一个子模式中的内容,用这个内容就可以找到在变量池中想要输出的内容。

接下来就是最后的一个方法了,就是把内容显示出来的方法

public function display($templateName = null,$ext = ‘.html‘){
        $templateName = empty($templateName) ? $this->currentTemp : $templateName;
        include_once $this->compileDir.md5($templateName).$ext;
    }

获取文件名,连接路径,用include_once函数输出便可,至此我们的正则模版就定义好了。

接下来在原目录下新建一个php文件,命名为index.php

index.php中代码如下

<?php

require_once(‘template.class.php‘);

$baseDir = str_replace(‘\\‘,‘/‘,dirname(__FILE__));  //当前的目录,把\替换成/,__FILE__是一个魔术常量,表示当前文件目录
$temp = new template($baseDir.‘/source/‘,$baseDir.‘/compiled/‘);    //实例化一个模版对象,给源目录和编译放置目录

$temp->assign(‘test‘,‘imooc女神‘);
$temp->assign(‘pagetitle‘,‘山寨版smarty‘);                    //给变量池中加变量

$temp->getSourceTemplate(‘index‘);
$temp->compileTemplate();
$temp->display();

?>

与模版关联,后得到当前目录,创建一个对象,将要替换的值加入变量池,得到源文件中要编译的文件的目录(此处我们的例子是index.html),开始编译,然后输出

我们是在source下写了一个html页面,内容如下

<!DOCTYPE HTML>
<html>
 <head>
 <meta charset="utf-8">
  <title>{#$pagetitle#}</title>

 </head>

 <body>
  模版引擎测试:{#$test#}
 </body>
</html>

经过编译后在compiled下得到一个新的html文件,文件名经过加密,打开后得到如图效果

    

可见源文件中的$pagetitle,$test中已被替换成php中的输出语句,在浏览器中也显示出了应有的效果,我们的一个模仿Smarty就做好的

实际上的Smarty模版功能远比这个强大,但我们知其一便能知其二,慢慢添加完善,我们的模版也能很强大,哈哈!

时间: 2024-10-05 13:29:36

做一个模仿Smarty的简易模版的相关文章

jsPlumb插件做一个模仿viso的可拖拉流程图

前言 这是我第一次写博客,心情还是有点小小的激动!这次主要分享的是用jsPlumb,做一个可以给用户自定义拖拉的流程图,并且可以序列化保存在服务器端. 我在这次的实现上面做得比较粗糙,还有分享我在做jsPlumb流程图遇到的一些问题. 准备工作 制作流程图用到的相关的脚本: 1 <script src="<%= ResolveUrl("~/resources/jquery/jquery-1.11.1.min.js")%>" type="t

python之路-利用索引切片功能做一个简易的两个未知数的加法计算器,代码如下:

python之路-利用索引切片功能做一个简易的两个未知数的加法计算器,代码如下: #content = input('请输入内容:'),如用户输入:5 +9或 5 + 9 等,然后进行分割再进行计算. content = input('>>>').strip() #content 等于所输入的内容,strip:删除字符串左右两边的空格. index = content.find('+') ''' content内容中的两边的空格都删除了,但中间还有,现在我们只需要定位已知内容是加法,两边

python练习:做一个简易的课程设计。Student Information Management System

Student Information Management System 犹记得,大一时候,用C语言做这个课程设计,我特么一口老血都要喷出来,现在用Python做,反而有一种亲切感. 做一个menu菜单,在while循环里调用定义的insert(),delete(),modify(),sort(),display(),exit()等函数. import pickle as p import os #Class Item class Item: def __init__(self,name,ag

编写可维护的JavaScript之简易模版

/* * 正则替换%s * @para arg1(text) 需要替换的模版 * @para arg2 替换第一处%s * @para arg3 替换第二处%s * 返回替换后的字符串 */ var sprintf = function (text) { var i = 1, args = arguments, len = args.length; return text.replace(/%s/g, function () { return (i < len) ? args[i++] : &quo

使用Multiplayer Networking做一个简单的多人游戏例子-2/3(Unity3D开发之二十六)

猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/51007512 使用Multiplayer Networking做一个简单的多人游戏例子-1/3 使用Multiplayer Networking做一个简单的多人游戏例子-2/3 使用Multiplayer Networking做一个简单的多人游戏例子-3/3 7. 在网络中控制Player移动 上一篇中,玩家操

TinyWS —— 一个C++写的简易WEB服务器(一)

写在前面 每个码农可能都会偶尔有自己做一个常用软件的想法,比如操作系统,编译器,邮件服务器/客户端,文字编辑器等等.这里面有些很难,比如操作系统,做一个最简单的也要付出很大的努力,可是大部分常用工具都是可以比较容易的做一个简易版本(当然也是只能玩玩而已).于是我做了一个非常简陋的WEB服务器 —— TinyWS.这里主要是记录下自己整个过程中的一些想法. TinyWS是用C++”从头开始“做的,也就是说,除了C/C++的标准库和操作系统的系统调用,并没有使用第三方库.我并不喜欢C++(甚至有些厌

做一个互联网+时代的新农民

在村里,每天零晨闻鸡鸣,因为太宁静,鸡鸣就显得特别地高亢嘹亮,今天干脆做一个闻鸡起舞之人,来简单梳理这两天边做农民边思考的问题.技术发展得太快了,这些年感觉都在追赶,我们似乎只是国外的跟屁虫,但国外是相当害怕的,他们自以为无法超越的东西,我们从模仿到超越也就很短的时间,当然除了核心技术,我们是没有耐心也无法静下心来钻研的,比如操作系统和数据库系统之类的,就算我们再狠狠地干个几十年,依然是扶不起的. 如今,不知不觉就来到了互联网+时代,DT时代,感觉我们还没有学会好好地走路,就开始飞翔了,连一个网

如何做一个开心的程序员?

经常有人发帖讨论「怎么做一个成功的程序员」,「如何才能成为一个优秀的程序员」,我并不太同意这些文章中的看法,想在这里我想提出一些我对于程序员这个职业自己的想法. 和标题中写的一样,我的目标不是成为一个优秀或者成功的程序员,我想成为一个开心的程序员.因为程序员是一个工作和生活密不可分的职业只有成为一个开心的程序员,才能过着开心的生活. 我相信那些想让自己或者别人成为优秀的程序员的人的最终目的也是能过上更开心的生活:少一点烦恼,多一点自由做自己想做的事情. 可能大家会不太同意我对开心的生活的定义,这

我是怎么4个小时从0做一个网站的

万事皆有因 近期公司的事情我基本上不太能插上手写代码(当领导了,天天写邮件和整理Excel),但是做为一个前主程怎么忍心让自己的技能荒废了呢(其实已经自废武功:Ruby on Rails完全忘的差不多了)?再和小伙伴们做一个项目A的时候,偶然间想起了我手里还有个域名ailink.io还是挺上口的(鬼知道我当时怎么想的要买这域名),再加上自己对Lisp大法的一些情怀(Emacs用多了的后遗症,早几年发现intelliJ,大概我和Lisp就没啥关系了).然后就开始作为项目A的子功能先行开发完成了,并