织梦动态模板引擎标签自定义属性详解
首先,要对标题说明一下要不可能理解有误,这里的织梦标签指的是动态模板引擎编译的标签,也就是后台里面像content_list.htm模板里面用到的标签,而不是前台/tempplets/defualt/里面的模板的标签,这是静态模板引擎那套系统了。
其次,这里的自定义属性是指自已定义标签的属性,而不是“自定义属性”,是自己定义标签的属性的意思。
举例说明:本例是以分页标签{dede:pagelist/}为例子,我们知道这个标签有二个属性,一个是列表大小listsize,它指的是分页导航显示的数字个数,如果listsize=3则表示显示的数字个数为3*2+1=7,一个是listitem,这个显示的是“上一页”、“下一页”、“首页”等。
现在我想自己定义这个标签{dede:pagelist listsize=3,listitem="index,pageno"/}的属性,即,我想在这个标签里添加一个属性site,这个属性的值为www.dedebase.com,即{dede:pagelist listsize=3 listitem="index,pageno"site="www.dedebase.com"/}。
本教程就是对这个功能的实现进行详细的分析,要想自己去定义织梦标签的属性,首先弄明白这样可以吗?要知道可不可以,首先得弄明白标签{dede:pagelist/}实现的原理,只有把原理弄明白了,才能进行标签的二次开发,否则一切都是空谈,所以,现在的问题是首先我们得分析一下这个标签的实现的原理,其实,这个在教程“”里已经作了详解,但是,那个还不够,这里我再更细的分析一下这个标签,以对那个教程补充。
织梦动态标签编译运行原理:模板标签通过模板引擎——>编译成php代码——>生成缓存文件——>把缓存文件引入到content_list.php文件,这时因为content_list.php实例化了一个分页类,所以,这个缓存文件的php代码就可以调用分页类里面的GetPageList($atts,$refObj='',$fields=array())了,这个函数就是具体我们在后台看到的分页如下图所示。
上面标签编译原理只是一个简单的流程,现在我们分析一下标签编译功能。
这个标签是通过模板引擎dedetemplate.class.php里面下面的代码来编译成php代码的:
else if( $tagname=='pagelist' ) { //生成属性数组 foreach($cTag->cAtt->items as $k=>$v) { $v = $this->TrimAtts($v); $rsvalue .= '$atts[\''.$k.'\'] = \''.str_replace("'","\\'",$v)."';\r\n"; } $rsvalue = '<'.'?php'."\r\n".'$atts = array();'."\r\n".$rsvalue; $rsvalue .= ' echo $this->refObj->GetPageList($atts,$this->refObj,$fields); '."\r\n".'?'.">\r\n"; $cTag->tagValue = $rsvalue; }
从这段代码里我们可以看出,标签{dede:pagelist/}里的属性是通过遍历$cTag->cAtt->items,然后,把键值存入到$atts数组里面,这里面的键和值,分别为标签的属性和属性值,例如listsize=3。这就是为什么我们编译标签后的php代码像下面这样了。
<?php $atts = array(); $atts['tagname'] = 'pagelist'; $atts['listsize'] = '3'; $this->refObj->GetPageList($atts,$this->refObj,$fields) ?>
数组$cTag->cAtt->items是在解析模板函数ParseTemplate()里面生成的,为了更好的理解我重新把模板引擎各个函数进行整理一下,看看每个函数都做哪些事情,也就是动态模板引擎的执行流程中各个函数做的事情:
1.载入模板文件:LoadTemplate($tmpfile)
载入模板后:就建立缓存文件,也就是文件夹data/tplcache里面的,但是此时,并没有写入任何东西,也没有在这个目录里生成这个缓存文件,只是在这一个函数里面定义了缓存文件名。然后把模板字符串(也就是处理后的模板)放在$this->sourceString里面。
2.解析模板:ParseTemplate()
把$this->sourceString里面的标记和属性以及属性值都放在标记数组$this->cTags里面。我们可以打印一下$this->cTags里面的具体内容,在函数ParseTemplate()里面加上如下代码:
echo "<pre>"; print_r($this->cTags[$this->count]); echo "</pre>";
得到的结果是:
Tag Object ( [isCompiler] => [tagName] => pagelist [innerText] => [startPos] => 5528 [endPos] => 5616 [cAtt] => TagAttribute Object ( [count] => 3 [items] => Array ( [tagname] => pagelist [listsize] => 3 [listitem] => index pageno prenext form [site] => www.dedebase.com ) ) [tagValue] => [tagID] => 9 )
我只截取标签为{dede:pagelist listsize=3 site="www.dedebase.com"/}的一个结果,其它结构完全一样,只是具体值不一样,从这个结果我们就可以知道$cTag->cAtt->items代码的是什么了吧?不就是一个数组吗!
3.把模板标记转换为PHP代码:
CompilerAll(),从$this->cTags里面遍历出标记以及标记的属性和属性值,对它们处理,处理后的php代码,替换模板里面的标签,然后,把替换后的字符串保存到$this->sourceString里面。
4.显示内容:Display()
通过函数WriteCache()把上一步替换后的模板字符串,也就是$this->sourceString写入缓存文件,然后,通过include把这个缓存文件引入到contnte_list.php里面。
5.因为,content_list.php里面实例化了一个分页类,而这时替换后的模板文件里面的标签已经是一些php代码了,所以,可以直接使用分页类里面的方法。
通过上面的流程我们就知道了,在第三步就已经生成了标记、属性以及属性值了,而这些都是标签{dede:pagelist listsize="3"/}里面定义的,上面流程告诉我们:编译模板标签为php代码,而php代码是通过模板里面的标签设置的内容进行编译,也就是说,模板引擎只是被动的接受标签来进行编译。
这样我们就可以知道标签写什么属性,值,甚至标记都是由我们决定的,我们在标签类似{dede:pagelist listsize=3/}写任何内容,模板引擎都会给我们编译出来,至于,能不能调用数据来,那是另外一回事。但是,无论我们在标签里面写什么东西,模板引擎都可以给我们编译成php代码,因为,我们在模板自己去定义标签后,这些自己去定义的标签就会被模板引擎保存起来,然后,再把这些标签里面的内容,遍历出来,生成php代码,而且这个编译php代码的功能,也可以去自己定义。
从这个标签被编译成上面的php代码,我们就可以得出这样的结论:标签里面的属性及其值可以自己去定义,定义好后,就可以显示对应的php代码,而且,标签的编译也可以自己去定义。
知道了上面的原理,我们现在才真正开始去自己定义标签属性了。
实验开始:
在织梦模板文件content_list.html里面的标签{dede:pagelist listsize=3/}里面加上一个属性site="www.dedebase.com",即{dede:pagelist listsize=3 site="www.dedebase.com"/}这个在织梦默认的系统里面并没有这个属性,我加上后看看能不能正常显示。
结果没有问题,我们去看一下生成的缓存文件如下图所示。
大家看到没有,多了一个属性$atts['site']='www.dedebase.com',再看一下后台也是正常显示,这是肯定的,因为上面的原理已经告诉我们一定会正常的。
自定标签我们是会了,但是,这个只是定义了一个标签,也不没有什么用,他不像listsize=3一样可以起来显示效果,所以,接下来的问题,我要完善一下这个标签,让我们自己定义的标签属性也起作用。
我们看到上图中有这么一行编译后的代码:$this->refObj->GetPageList($atts,$this->refObj,$fields)
上面我们提到过这个缓存文件会被引入到content_list.php文件里面,当然,这一行代码也会被引入到这个文件里面,其中,在这个content_list.php文件里面,我们已经实例化了一个分页类,代码如下:$dlist=new DataListCP();
再看上面的$this->refObj->GetPageList(),这个$this->refObj就是$dlist,若弄明白了这个,我们就知道了,这个函数GetPageList(),也就是$dlist->GetPageList(),也就是公页类的一个方法,这个正是分页导航函数,后台里面的导航全是由它来实现的。
所以,要使用属性site="www.dedebase.com" 也起作用,就要对函数$dlist->GetPageList()进行二次开发,在函数里面我加上了如下代码。
然后在模板content_list.htm里面我的标签代码如下图所示。
然后,到后台去看一下分页导航是不是多了一个功能,如下图所示。
果然,多了我们写的那个功能,只是这个功能是用来显示字符串“织梦基地网址:www.dedebase.com”罢了,这个你个人可以自己发挥实现什么样的功能都可以。
如果我想自己定义标记呢?也就是标签{dede:pagelist listsize=3/}里面的pagelist标记,例如我想定义一个标记为pagetitle,当然,完全可以。只不过这个要修改模板引擎文件了。