织梦动态模板引擎标签自定义属性详解

admin2023-01-191128

首先,要对标题说明一下要不可能理解有误,这里的织梦标签指的是动态模板引擎编译的标签,也就是后台里面像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())了,这个函数就是具体我们在后台看到的分页如下图所示。

360截图17001016587880.jpg

上面标签编译原理只是一个简单的流程,现在我们分析一下标签编译功能。

这个标签是通过模板引擎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-&gt;cAtt-&gt;items是在解析模板函数ParseTemplate()里面生成的,为了更好的理解我重新把模板引擎各个函数进行整理一下,看看每个函数都做哪些事情,也就是动态模板引擎的执行流程中各个函数做的事情:

1.载入模板文件:LoadTemplate($tmpfile)

载入模板后:就建立缓存文件,也就是文件夹data/tplcache里面的,但是此时,并没有写入任何东西,也没有在这个目录里生成这个缓存文件,只是在这一个函数里面定义了缓存文件名。然后把模板字符串(也就是处理后的模板)放在$this-&gt;sourceString里面。

2.解析模板:ParseTemplate()

把$this-&gt;sourceString里面的标记和属性以及属性值都放在标记数组$this-&gt;cTags里面。我们可以打印一下$this-&gt;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-&gt;cAtt-&gt;items代码的是什么了吧?不就是一个数组吗!

3.把模板标记转换为PHP代码:

CompilerAll(),从$this-&gt;cTags里面遍历出标记以及标记的属性和属性值,对它们处理,处理后的php代码,替换模板里面的标签,然后,把替换后的字符串保存到$this-&gt;sourceString里面。

4.显示内容:Display()

通过函数WriteCache()把上一步替换后的模板字符串,也就是$this-&gt;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"/}这个在织梦默认的系统里面并没有这个属性,我加上后看看能不能正常显示。

结果没有问题,我们去看一下生成的缓存文件如下图所示。

154729h839bo8boanlslmn.png

大家看到没有,多了一个属性$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里面我的标签代码如下图所示。

360截图17571115594842.jpg

然后,到后台去看一下分页导航是不是多了一个功能,如下图所示。

360截图187201204892107.jpg

果然,多了我们写的那个功能,只是这个功能是用来显示字符串“织梦基地网址:www.dedebase.com”罢了,这个你个人可以自己发挥实现什么样的功能都可以。

如果我想自己定义标记呢?也就是标签{dede:pagelist listsize=3/}里面的pagelist标记,例如我想定义一个标记为pagetitle,当然,完全可以。只不过这个要修改模板引擎文件了。


网友评论