Salad UN

To Taste The Salad Of Life.

« KingCMS安装在Godaddy修改记录-310个优秀的 Web UI 库/框架 »

认识DedeCms模板的勾子技术

[ At 2009-4-15 By Ash   0 comments ]

勾子技术DedeCms V5.3最大的改变之一,可能大家不大理解勾子这名称,说具体些,在DedeCms里有很多模板调用标签,实际上,这些标签是通过解析后,按不同名称和属性返回不同内容来替代的,在不使用模板引擎的情况下,一个函数调用就可以认为是勾子的一种体现,这也是一些论坛程序的做法,但这种做法始终需要在核心一些文件加入一些代码,即使是最简单的代码,对升级显然是有一定麻烦的,而DedeCms V5.3的勾子技术则改变了这种做法,它的原理与一些框架的MVC机制类似,不过它不是动态产生触发器,而是动态解析标签。
    什么是动态解析标签?简单的来说就是模板里存在什么标记就调用什么代码去解析,这样不必要载入一些多余的代码,而且扩展更加灵活,在具体说明前,先用一个例子简单说明DedeCms模板引擎的使用。

以下示例代码可以放在安装了dedecms系统的根目录中使用。
  1. <?php   
  2. //引入必须文件   
  3. require_once(dirname(__FILE__)."/include/commin.inc.php");   
  4. require_once(dirname(__FILE__)."/include/channelunit.func.php");   
  5. require_once(dirname(__FILE__)."/include/dedetag.class.php");   
  6.   
  7. //初始化模板类   
  8. $dtp = new DedeTagParse();   
  9. $dtp->SetNameSpace("dede","{","}");   
  10.   
  11. //引用当前类([1]这里为空,后面会说明用途)   
  12. $dtp->refObj = null;   
  13.   
  14. //载入模板   
  15. $dtp->LoadTemplet($filename);   
  16.   
  17. //动态解析 include/taglib 里的标签 [2]   
  18. MakeOneTag($dtp, null);   
  19.   
  20. //解析系统标签,显示内容   
  21. $dtp->Display();   
  22.   
  23. //类似方法:GetResult() 获得解析后的HTML,SaveTo($filename)保存为文件   
  24.   
  25. ?>   
  26.     

在以上例子中,比较不好理解的是两个 null,其实如果在类中调用这模板类,通常表示为 $this
具体原因需要分析 channelunit.func.php 里的

MakeOneTag(&$dtp,&$refObj)

这个函数的第一个参数不用说都知道是模板类本身的对象实例,如$refObj就是引入这个模板类的类,在Dedecms中,凡是 include/arc. 开头的文件都是这种文档解析类的具体功能类。

它的具体代码如下:
  1. function MakeOneTag($dtp,$refObj)   
  2. {   
  3.         $alltags = array();   
  4.   
  5.         //读取自由调用tag列表   
  6.         $dh = dir(DEDEINC.'/taglib');   
  7.         while($filename = $dh->read())   
  8.         {   
  9.                 if(ereg("\.lib\.",$filename))   
  10.                 {   
  11.                         $alltags[] = str_replace('.lib.php','',$filename);   
  12.                 }   
  13.         }   
  14.         $dh->Close();   
  15.   
  16.         //遍历tag元素   
  17.         if(!is_array($dtp->CTags))   
  18.         {   
  19.                 return '';   
  20.         }   
  21.         foreach($dtp->CTags as $tagid=>$ctag)   
  22.         {   
  23.                 $tagname = $ctag->GetName();   
  24.                    
  25.                 //解析通用的 field 标签 [1]*   
  26.                 if($tagname=='field')   
  27.                 {   
  28.                         $vname = $ctag->GetAtt('name');   
  29.                         if(isset($refObj->Fields[$vname]))   
  30.                         {   
  31.                                 $dtp->Assign($tagid$refObj->Fields[$vname]);   
  32.                         }   
  33.                         else if( isset( $this->TypeLink->TypeInfos[$vname] ) )   
  34.                         {   
  35.                                 $dtp->Assign($tagid$this->TypeLink->TypeInfos[$vname]);   
  36.                         }   
  37.                         continue;   
  38.                 }   
  39.   
  40.                 //同名标记(兼容旧版)处理   
  41.                 if(ereg("^(artlist|likeart|hotart|imglist|imginfolist|coolart|specart|autolist)$",$tagname))   
  42.                 {   
  43.                         $tagname='arclist';   
  44.                 }   
  45.                 if($tagname=='friendlink')   
  46.                 {   
  47.                         $tagname='flink';   
  48.                 }   
  49.                    
  50.                 //给不同的标记调用不同的解析文件 [2]*   
  51.                 if(in_array($tagname,$alltags))   
  52.                 {   
  53.                         $filename = DEDEINC.'/taglib/'.$tagname.'.lib.php';   
  54.                         include_once($filename);   
  55.                         $funcname = 'lib_'.$tagname;   
  56.                         $dtp->Assign($tagid,$funcname($ctag,$refObj));   
  57.                 }   
  58.         }   
  59. }  

以上代码的重点就是 [1] [2] 标注的地方
[1]是解析文档中field标签,这个标签对于文档类中,都必使用 var Fields; 数组来表示这些通用文档字段,但对于不同模板,它的值也是可变的。
[2]就是勾子技术的关键,给field以及系统标记以外的标记调用不同的具体解析代码,这里规定了这些代码必须放在include/taglib文件夹内,名称为“标记名.lib.php”

这个文件里定义的接口函数格式为:
  1. <?php   
  2. if(!defined('DEDEINC'))   
  3. {   
  4.         exit("Request Error!");   
  5. }   
  6. function lib_标记名称($ctag,$refObj)   
  7. {   
  8.         global $dsql,$envs;   
  9.            
  10.         //属性处理   
  11.         $attlist="row|12,titlelen|24";   
  12.         FillAttsDefault($ctag->CAttribute->Items,$attlist);   
  13.         extract($ctag->CAttribute->Items, EXTR_SKIP);   
  14.         $revalue = '';   
  15.            
  16.         //你需编写的代码,不能用echo之类语法,把最终返回值传给$revalue   
  17.         //------------------------------------------------------   
  18.            
  19.         $revalue = 'Hello Word!';   
  20.            
  21.         //------------------------------------------------------   
  22.         return $revalue;   
  23. }   
  24. ?>  

到这里就完全揭开了DedeCms V5.3勾子技术的真正面目,上面还有一个没交待清楚的是
“$dtp->refObj = null;” 这个地方,其实对于Dedecms的文档解析类,100%都是面向对象的,它在类里通常是写为
“$this->dtp->refObj = $this;” 这个对象正是 function lib_标记名称(&$ctag,&$refObj) 里的第二个参数,说到这里,有点明白它的作用了吧,简单的来说就是在接口函数里获取当前解析类的一些相关信息,这是相当有用的。

来源:落伍论坛 [建站程序] 

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 1.8 Spirit Build 80722 Code detection by Codefense

Copyright 2008 www.s-un.cn. Some Rights Reserved.