dedeCMS模板原理

勾子技術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. $dtp = new DedeTagParse();
  8. $dtp->SetNameSpace("dede","{","}");
  9. //引用當前類([1]這裏爲空,後面會說明用途)
  10. $dtp->refObj = null;
  11. //載入模板
  12. $dtp->LoadTemplet($filename);
  13. //動態解析 include/taglib 裏的標籤 [2]
  14. MakeOneTag($dtp, null);
  15. //解析系統標籤,顯示內容
  16. $dtp->Display();
  17. //類似方法:GetResult() 獲得解析後的HTML,SaveTo($filename)保存爲文件
  18. ?
  19. 在以上例子中,比較不好理解的是兩個 null,其實如果在類中調用這模板類,通常表示爲 $this

    具體原因需要分析 channelunit.func.php 裏的

    MakeOneTag(&$dtp,&$refObj)

    這個函數的第一個參數不用說都知道是模板類本身的對象實例,如$refObj就是引入這個模板類的類,在Dedecms中,凡是 include/arc. 開頭的文件都是這種文檔解析類的具體功能類。

    它的具體代碼如下:

    以下爲引用的內容:

    1. function MakeOneTag(&$dtp,&$refObj)
    2. {
    3. $alltags = array();
    4. //讀取自由調用tag列表
    5. $dh = dir(DEDEINC.'/taglib');
    6. while($filename = $dh->read())
    7. {
    8. if(ereg("/.lib/.",$filename))
    9. {
    10. $alltags[] = str_replace('.lib.php','',$filename);
    11. }
    12. }
    13. $dh->Close();
    14. //遍歷tag元素
    15. if(!is_array($dtp->CTags))
    16. {
    17. return '';
    18. }
    19. foreach($dtp->CTags as $tagid=>$ctag)
    20. {
    21. $tagname = $ctag->GetName();
    22. //解析通用的 field 標籤 [1]*
    23. if($tagname=='field')
    24. {
    25. $vname = $ctag->GetAtt('name');
    26. if(isset($refObj->Fields[$vname]))
    27. {
    28. $dtp->Assign($tagid, $refObj->Fields[$vname]);
    29. }
    30. else if( isset( $this->TypeLink->TypeInfos[$vname] ) )
    31. {
    32. $dtp->Assign($tagid, $this->TypeLink->TypeInfos[$vname]);
    33. }
    34. continue;
    35. }
    36. //同名標記(兼容舊版)處理
    37. if(ereg("^(artlist|likeart|hotart|imglist|imginfolist|coolart|specart|autolist)$",$tagname))
    38. {
    39. $tagname='arclist';
    40. }
    41. if($tagname=='friendlink')
    42. {
    43. $tagname='flink';
    44. }
    45. //給不同的標記調用不同的解析文件 [2]*
    46. if(in_array($tagname,$alltags))
    47. {
    48. $filename = DEDEINC.'/taglib/'.$tagname.'.lib.php';
    49. include_once($filename);
    50. $funcname = 'lib_'.$tagname;
    51. $dtp->Assign($tagid,$funcname($ctag,$refObj));
    52. }
    53. }
    54. }
    55. 以上代碼的重點就是 [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. $attlist="row|12,titlelen|24";
      11. FillAttsDefault($ctag->CAttribute->Items,$attlist);
      12. extract($ctag->CAttribute->Items, EXTR_SKIP);
      13. $revalue = '';
      14. //你需編寫的代碼,不能用echo之類語法,把最終返回值傳給$revalue
      15. //------------------------------------------------------
      16. $revalue = 'Hello Word!';
      17. //------------------------------------------------------
      18. return $revalue;
      19. }
      20. ?>
      21. 到這裏就完全揭開了DedeCms V5.3勾子技術的真正面目,上面還有一個沒交待清楚的是

        “$dtp->refObj = null;” 這個地方,其實對於Dedecms的文檔解析類,100%都是面向對象的,它在類裏通常是寫爲

        “$this->dtp->refObj = $this;” 這個對象正是 function lib_標記名稱(&$ctag,&$refObj) 裏的第二個參數,說到這裏,有點明白它的作用了吧,簡單的來說就是在接口函數裏獲取當前解析類的一些相關信息,這是相當有用的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章