ecshop源码分析:smarty模板类
来源:互联网 发布:c语言连用else if 编辑:程序博客网 时间:2024/04/30 07:18
花了差不多3天半的时间,基本上把ecshop1400多行的模板类源码阅读完毕。从构造函数一行一行的阅读下去,遇到方法的调用便进去,遇到返回值又回到调用它的地方,这样来回不知道多少遍,每次阅读都让我心奋不已。之前一直都在使用smarty,却不知道它的工作原理,现在终于大概有个详细并全面的了解了,怎能不兴奋。现在,给大家分享我在看源码总结出的smarty的工作流程以及smarty标签的使用模板类工作流程
1.首先实例化模板类,构造函数基本没做什么工作,对象变量为$smarty。调用$smarty->assign(var,value),在assign()方法里把该变量和值装入$this->_var数组中:如果var是数组,如$smarty->assign(array(‘var1’=>val1,’var2’=>val2))则在$this->_var表示为:$this->_var[‘var1’]=val1、$this->_var[‘var2’]=val2…,如果是字符串:$this->_var[‘var’]=value。
2.调用:$smarty->display(‘index.html’);display()几乎没做多少工作,而是交给其他几个函数处理:首先display()内部调用fetch(‘index.html’)方法,把模板文件名作为参数传递过去;
3.fetch()是一个处理模板文件的方法,它做了许多条件判断分别进入到不同的处理语句,最主要的是它又调用了模板类的一个方法make_compiled()模板文件名作为参数传递过去;
4.make_compiled()是一个编译模板的方法:首先取得编译文件的绝对路径(前一部分是固定的,ecshop的后台前一部分编译路径C:\AppServ\www\ecshop\temp\compiled\admin\,后一部分是根据模板文件名设定,如模板为index.html,那后一部分就是index.html.php),接下来做判断,如果模板文件的修改时间小于等于编译文件的修改时间,则直接获取编译文件(这部分还会调用一个方法,稍后再说),反之,则重新编译模板文件:将模板文件的全部内容获取(file_get_contents)并把这些内容传给fetch_str()方法,由它处理。对fetch_str()返回的内容,把他们存入编译文件(php文件)中,到这里已经完成了模板文件的编译工作,随后就是执行编译文件,向浏览器输出内容了,这个工作由_eval()方法完成,把fetch_str()返回的内容作为_eval()的实参,这个方法很简单,直接把代码粘上来:function _eval($content){ob_start();//开启缓冲 eval('?' . '>' . trim($content));//'?'.'>'是为了闭合前面的PHP代码 $content = ob_get_contents();//获取缓冲内容 ob_end_clean();//清除缓冲区return $content; }最后把_eval()返回的值return给fetch(),fetch()也基本原样返回给display(),最后在dislay()中echo 该返回值。
5.fetch_str()一个处理字符串的方法:他需要一个参数,即是传递过来的模板文件的内容。它的工作是把在模板文件中类似<?php或<?=或?>或language="php"的字符串转换为%%%SMARTYSP0%%%类似字符(这部分暂时还不知道为什么这样做,大概是为了清除掉php起始和闭合标签),最后的一行代码完成了它应完成的功能:return preg_replace("/{([^\}\{\n]*)}/e", "\$this->select('\\1');", $source);这个正在表达式的功能是对模板中的标签{}之内的内容交由方法select()处理,传递的参数就是在模板中变量说明那里说到的一个字符串,但不包括{}。如模板中有标签{$var|nl2br}传给select的参数就是’$var|nl2br’(注:这只是一个字符串,不要以为有$就是变量)。把select()的返回值替换掉模板中匹配的内容后,将所有替换的内容返回给make_compiled (),即编译完成,接下来就由make_compiled ()把这些内容存入文件里了;6.select($tag)一个处理{}标签的方法:这个方法条件分支多,在阅读源码的时候应该一个一个分支阅读下去,遇到其他方法的调用就进去,切记不要操之过急。该方法首先判断传进来的$tag(即{}标签内的内容)是否为空,如果为空则返回’{}’即原样输出;判断$tag的首字母和尾字母是否都为*,如果是,则返回空,这部分是模板的注释,在编译文件中不会显示;判断$tag首字母是否为’$’,如果有,表示这是一个变量,把这个字符串的首字母’$’截掉后传递给get_val()方法,交给他处理。对get_val()的返回值类似:’$this->_var[‘str’]’,select()方法处理成’<?php echo $this->_var[‘str’];?>’字符串后返回给fetch_str();判断$tag首字母是否为’/’,表示这是个结束标签,如{/if}转为’<?php endif; ?>’;最后如果以上都不是,又需要经过许多判定处理,这部分的语句可以把{if}、{foreach}等解析。
7.get_val($val)一个处理smarty标签中的变量标签方法:如果$val值类似arr[0][1]、arr[str]、arr[$var]等,则替换为arr.0.1、arr.str、arr.$var并把替换后的值赋给$val覆盖原先的值;如果$val(是之前覆盖的值,如果有的话)的值包含’|’字符,’|’后面是过滤函数的名称,对$val使用$moddb =explode('|', $val); $val = array_shift($moddb);将第一个元素弹出,并把其值赋给$val,在对$moddb遍历,把过滤函数应用make_val()返回的在变量上。例如:如果$val=arr.str|nl2br则最后$val=arr.str,$moddb=array(‘nl2br’);对于arr.str和arr.$var(点号之后又有$)get_val有不同的处理方法:对于’arr.str’或’str’或’arr.0.1’,直接交由make_val()方法处理;对于’arr.$var’或’arr.$var1.$var2’,说明不仅arr是个变量,$var1和$var2也是变量,它们都存在$this->_var数组里(如果assign()注入了的话),把他们通过’.$’分开在分别交由make_val()处理,我们知道make_val()会返回类似’$this->_var[‘arr’]’的字符串,所以在get_val()中只是对’var1’和’var2’make_val()返回的字符串两侧加上’[‘、’]’,最后构成一个表示一维或多维数组的字符串:”$this->_var[‘arr’][$this->_var[‘var1’]][$this->_var[‘var2’]]”,最后将此字符串返回给select();
模板标签的使用
1.{*...*}模板的注释,在编译文件里里面的内容会为空
2.{$var}、{$arr[0]}、{$arr[$var]}、{$arr.var}、{$var1|htmlspecialchars }模板中的变量表示方式
其中{$var1|htmlspecialchars}“|”后面的字符串是对变量的过滤函数:其可以使用多种过滤函数:{$var|escape:fucstr}冒号后面的fucstr和他所代表的函数可是:
html : htmlspecialchars
url : urlencode
decode_url : urldecode
quotes : addslashes
u8_url : if (EC_CHARSET != 'utf-8'){ $p = 'urlencode(ecs_iconv("' . EC_CHARSET .'", "utf-8",' . $p . '))';}else{ $p = 'urlencode(' . $p . ')';}
如果没有冒号后面的默认是htmlspecialchars
还有:{$var|nl2br} : nl2br($var)
{$var|default} : empty($var)?’’:$var
{$var1|default:$var2} : empty($var1)?$var2:$var1
{$var|default:str} : empty($var)? ’str’ :$var1
{$var|truncate:number} : sub_str($var,number)(注:sub_str是ecshop的一个自定义函数,可以截取中文)
{$var|strip_tags} : strip_tags($var)
以上可在在模板类cls_template.php文件的get_val()方法里找到3.{if}标签:用法{if $arr.str eq 1}{/if} (每个字符串至少用一个空格隔开)。关系运算符eq:==,ne或neq:!=,lt:<,le或lte:<=,gt:>,ge或gte:>=,and:&&,or:||,not:!,mod:%。以上都可以使用大写,也可以用他们本身替代。对$arr.str的处理使用get_val(‘arr.str’)方法,下面模板工作流程里会介绍,最后编译为:<?phpif($this->_var[‘arr’][‘str’] == 1): ?>。也可在{if}{/if}里使用{else}和{elseif},对{else}的处理是直接返回’<?php else: ?>’,对{elseif}的处理和{if}类似。
4.{foreach}标签:用法{foreach from=$arr item=val key=k name=n}{$val}{/foreach}key和name可以不设置。可以嵌套多个{foreach}标签,可以使用{foreachelse}。对{foreach}标签的解析方式看以查看_compile_foreach_start()函数。
5.{assign}标签:用法{assignvar=user value=hzn}用于在模板中注册变量,在编译文件中解析为:<?php $this->assign(‘user’,’hzn’); ?>。value也可以使用变量但name不行{assignvar=user value=$hzn}解析为:<?php $this->assign(‘user’,$this->_var[‘hzn’]) ?>
6.{include}标签:用法{includefile=other.html}用于包含模板文件。文件名可以加单引号护双引号。(注:other.html所用到的变量,需要从引用这个文件的模板文件的对应php文件注入)
7. {insert_scripts}标签:用法{insert_scripts files=”../js/utils.js,listtable.js”}可以引入一个或多个js脚本,多个文件之间用逗号隔开。文件以“.”开头的,表示<scripttype="text/javascript" src="../js/utils.js"></script>,没有点号开头<scripttype="text/javascript" src="js/listtable.js"></script>总会在文件名之前加上’js/’,可以在方法smarty_insert_scripts()更改。
8.{ create_pages}标签:用法{create_pages page=1 count=10}生成一个下拉列表。可以用作分页列表。
9.{insert}标签:用法{insert name=”fuc” id=$id type=”text”}在编译文件执行时调用insert_fuc()这个函数(fuc名称可以自定),该方法可以传递一个数组作为参数:array(‘name’=>’fuc’,’id’=>$this->_var[‘id’],’type’=>’text’)。这个标签在编译文件中编译为:
<?php $k = array ( 'name' => 'strlen', 'id' => $this->_var['id'], 'type' => 'text',);echo $this->_echash . $k['name'] . '|' . serialize($k) . $this->_echash;?>初看起来让人摸不着头脑,在到display()方法去看就明白了。其实在display()已经把编译文件执行了,所以缓冲的内容里是以$this->_echash(一个很长的字符串)分成了三部分,对$k['name'] . '|' .serialize($k)进行处理再把三部分合并输出。
10.{literal}标签:用法{literal}{/literal}原样输出标签中包含的内容
11.{cycle}标签:用法{cycle values=”blue,red,green”}循环输出values的内容,一个标签只能输出一个值,按顺序输出。
12.{html_options}标签:用法{html_options selected=”2” options=$arr}用于输出select标签的<option>标签。selected表示初始列表选定的值,options是一个数组,该数组的键值作为<option>的value,元素值作为<option>显示的值。另一种用法将value值和显示的值分开:
{html_options values=$valArr output=$opArr selected=”2”}如果没有values,output的键值作为<option>的value
13.{html_select_date}标签:用法{html_select_dateprefix="StartDate" time=$time start_year="-5"end_year="+1" display_days=”true” display_months=”false”}用于显示年月日的下来列表,prefix指定每个<select>name属性的前缀,如年份的<select name=”StartDateYear”>;time用来指定option的selected。start_year,end_year是年份下拉列表的开始日期和结束日期,可以是-5、+1(表示由当前日期减去或加上多少数值),也可以是2014四位数的形式;display_days和display_months如果设置为”false”则不显示天数和月数的下拉表。
14.{html_radios}标签:用法{html_radiosname="order" checked="3" options=$arr}显示单选按钮。
15.{html_select_time}标签:用法{html_select_timeprefix="myTime" time=$time display_hours="false"}显示时间下拉表。和html_select_date相似。
- ecshop源码分析:smarty模板类
- ecshop模板smarty foreach详解 [ECshop]
- ecshop模板smarty foreach详解
- ecshop模板smarty foreach详解
- ecshop模板smarty foreach详解
- ecshop模板smarty foreach详解
- ecshop模板的smarty foreach详解
- ECShop模板中smarty foreach标签详解
- ecshop源码分析-ecshop二次开发
- smarty模板进一步分析
- ecshop源码分析:会话类cls_session
- ECSHOP源码分析
- ecshop 二次开发,源码分析
- ecshop 源码分析
- ecshop 二次开发,源码分析
- ecshop 二次开发,源码分析
- ecshop源码分析01
- ecshop源码分析02
- The preprocessor
- B. Valera and Fruits
- ubuntu中root权限的获得及arm-linux-gcc交叉编译环境的搭建
- Filthy Rich
- F广搜
- ecshop源码分析:smarty模板类
- Java经典23种设计模式之行为型模式(二)
- JSON学习笔记
- [LeetCode] Combinations
- 验证日期是否正确
- XListView的介绍和使用
- TI C66x DSP 系统events及其应用 - 5.8(ISTP)
- 第三十四天 我为集成平台狂(七)-步履轻盈的JQuery(五)
- 如何增强你的SharePoint 团队网站首页