ThinkPHP3.0完全开发手册
任何一个模板引擎的功能都不可能是为你量身定制的,具有一个良好的可扩展机制也是模板引擎的另外一个考量,Smarty采用的是插件方法来实现扩展,ThinkTemplate由于采用了标签库技术,比Smarty提供了更为强大的定制功能,和Java的TagLibs一样可以支持自定义标签库和标签,每个标签都有独立的解析方法,所以可以根据标签库的定义规则来增加和修改标签解析规则。在ThinkTemplate中标签库的体现是采用XML命名空间的方式。
每个标签库对应一个标签库驱动类,每个驱动类负责对标签库中的所有标签的解析。标签库驱动类的作用其实就是把某个标签定义解析成为有效的模版文件(可以包括PHP语句或者HTML标签)。
系统的标签库驱动扩展目录位于Extend/Driver/TagLib目录下面,命名规范是:
TagLib+标签库名称(首字母大写)
目前已经提供了Html标签库驱动支持,标签库驱动扩展必须继承TagLib类,例如我们扩展一个Test标签库:
Class TagLibTest extends TagLib{}
首先需要定义标签库的标签定义,标签定义包含了所有标签库中支持的所有标签,定义方式如下:
protected $tags = array(
// 定义标签
'input'=>array('attr'=>'type,name,id,value','close'=>0), // input标签
);
标签库的所有支持标签都在tags属性中进行定义,tags属性是一个二维数组,每个元素就是一个标签定义,索引名就是标签名,采用小写定义,调用的时候不区分大小写。
每个标签定义支持的属性包括:
属性名 |
说明 |
attr |
标签支持的属性列表,用逗号分隔 |
close |
标签是否为闭合方式 (0闭合 1不闭合),默认为不闭合 |
level |
标签的嵌套层次(只有不闭合的标签才有嵌套层次) |
alias |
标签别名 |
定义了标签属性后,就需要定义每个标签的解析方法了,每个标签的解析方法在定义的时候需要添加“_”前缀,可以传入两个参数,属性字符串和内容字符串(针对非闭合标签)。必须通过return 返回标签的字符串解析输出,在标签解析类中可以调用模板类的实例。下面是一个input解析方法的定义:
public function _input($attr,$content) {
$tag = $this->parseXmlAttr($attr,'input');
$name = $tag['name'];
$id = $tag['id'];
$type = $tag['type'];
$value = $this->autoBuildVar($tag['value']);
$str = '<input type="'.$type.'" id="'.$id.'"name="'.$name.'" value="'.$value.'" />';
return $str;
}
在每个标签的解析方法中,首先需要调用
$this->parseXmlAttr($attr,'input');
表示分析input标签的标签定义,并返回input的所有标签属性。接下来就是根据具体的属性值来返回实际的解析内容了。由于是示例,我们没有对标签中的全部变量进行解析,只是支持了value属性的变量传入。
定义好标签库扩展之后,我们就可以在模板中使用了,首先我们必须要告诉模板申明Test标签库,用taglib标签,例如:
<taglib name='Test' />
name属性支持申明多个标签库,用逗号分隔即可。申明Test标签库之后,就可以使用Test标签库中的所有标签库了,调用方式如下:
<test:input type='radio' id='test' name='mail'value='value' />
注意:调用扩展标签库的标签的时候,必须加上标签库的XML命名空间前缀。
由于我们定义的input标签是闭合标签,如果是非闭合方式的话,应该是写成:
<test:input type='radio' id='test' name='mail' value='value'></test:input>
Input标签定义value属性可以支持变量传入,所以value被认为是一个变量名,如果在Action中已经给value模板变量赋值,例如:
$this->assign('value','my test value');
最后标签被模板引擎编译后,就会输出:
<input type='radio' id='test' name='mail' value='my test value'/>