dedecms核心類源碼分析


dedecms核心類源碼分析

   最近公司一個cms類型的項目,時間緊任務重。經過快速的決策后,選擇了dedecms開發1.0版本,滿足基本需求。以前從來沒有接觸過這個系統,而且此系統文檔是相當的不全。所以分析源代碼是最好的方式。學習一個系統,首要的是搞懂它的數據引擎、模板引擎。dedetag.class.php 這個文件就是核心底層模板解析引擎,其它的引擎都是在這個基礎上增加了自己的函數而已。

一、dedetag.class.php

 1.DedeTag :最后存儲的CTags的結構類,提供一些讀取CTags屬性的方法。(這個很重要)
    2.DedeAttribute : 最后存儲的CTags->attr 的屬性結構類(count,Items)
    3.DedeAttributeParse: 屬性解析器,解析提供屬性結構到CTags變量。
    4.DedeTagParse核心解析器      

 1        1.LoadTemplate 載入模板。
 2             1. while($line = fgets($fp,1024)) //line 379循環讀取文件賦值到變量 $this->SourceString .= $line;
 3             2. if($this->LoadCache($filename))//line 384在有緩存的情況,讀取緩存文件到 CTags
 4             3.  $this->ParseTemplet();//line 390 沒有緩存則調用模板解析方法
 5         2.ParseTemplet 解析模板
 6             1.循環遍歷,按正則匹配每個標簽的位子和屬性,並保存到 CTags
 7             2. $this->SaveCache(); //line 952 ,如果開啟緩存配置則保存到緩存文件
 8         3.GetResult 輸出模板
 9             1. $this->AssignSysTag();// line 738 處理特殊標記(global,include,foreach,var,runphp)(global模板,能處理模板上的函數,和10步一樣)      
10         4.AssignSysTag  處理特殊標記(global,include,foreach,var,runphp)(global模板,能處理模板上的函數,和10步一樣)
11         5.Assign         封裝模板的類(arclist/channel/memeberlist.....)和字段的解析是channelunit.helper.php中MakeOneTag函數在處理,
12             $dtp->Assign($tagid,$funcname($ctag,$refObj)); // line 558 調動地底層模板解析引擎的賦值函數為便簽賦值。            

二、arc.partview.class.php 分析

 1     index.php調用arc.partview.class.php
 2     1.$this->dtp = new DedeTagParse();//line 47 初始化底層模板解析引擎
 3     2.$this->SetTemplet();//line 134 讀取要解析的模板 
 4     3.$this->dtp->LoadTemplet($temp); //line 142 實際調用的是底層模板解析引擎 
 5     4.$this->ParseTemplet(); //line 149 封裝的解析模板方法
 6     5.MakeOneTag($this->dtp,$this); //line 224 這個函數放在 channelunit.func.php 文件中,
 7     6.helper('channelunit');// line 29 調用helper工具加載對應的函數。channelunit.helper.php
 8     7.if($tagname=='field' && $parfield=='Y') //line 515 解析field 模板
 9     8.$funcname = 'lib_'.$tagname; //line 557 加載對應的封裝模板的類(arclist/channel/memeberlist.....)
10     9.$dtp->Assign($tagid,$funcname($ctag,$refObj)); // line 558 調動地底層模板解析引擎的賦值函數為便簽賦值。
11    10.$this->$dtp->EvalFunc($fieldvalue,$functionname,&$refObj); //line 965 動地底層模板解析引擎處理某字段的函數(模板中直接使用函數最終也是調用的此方法加載對應的函數返回值)
12    11.$this->dtp->GetResult();//line 169 調動地底層模板解析引擎的輸出方法
13    12.$this->dtp->AssignSysTag(); //line 738  調動地底層模板解析引擎處理特殊標記(global,include,foreach,var,runphp)(global模板,能處理模板上的函數,和10步一樣)
14    13.$this->dtp->CTags[$i]->TagValue = $str; 每一次解析模板賦值都會修改CTags的TagValue
15    
16    總結:封面模板解析類是對 dedetag.class.php 的封裝。加入了一些自己的處理邏輯

三、寫自己的模板解析

      

    
  1 <?php 
  2 require_once(dirname(__FILE__)."/../include/common.inc.php");
  3 require_once(DEDEINC.'/channelunit.class.php');
  4 require_once(DEDEINC.'/typelink.class.php');
  5 require_once(DEDEINC.'/ftp.class.php');
  6 /**
  7  * 模板調用事例
  8  *
  9  * @version        2018-11-01
 10  * @package        1.0.1
 11  * @author         main_wu
 12  */
 13 class TestView
 14 {
 15     public $dsql;
 16     public $dtp;
 17     public $TypeID;
 18     public $Fields;
 19     public $TypeLink;
 20     public $pvCopy;
 21     public $refObj;
 22     public $ftp;
 23     public $remoteDir;
 24 
 25     public function __construct($typeid=0, $needtypelink=true)
 26     {
 27         global $_sys_globals,$ftp;
 28         $this->TypeID = $typeid;
 29         $this->dsql = $GLOBALS['dsql'];
 30         $this->dtp = new DedeTagParse();
 31         $this->dtp->SetNameSpace("dede", "{", "}");
 32         $this->dtp->SetRefObj($this);
 33         $this->ftp = &$ftp;
 34         $this->remoteDir = '';
 35         //加載模板->解析模板
 36         $this->dtp->LoadTemplet(DEDETEMPLATE ."/default/test.htm");
 37 
 38         //字段,通過{dede:filed.myname}訪問到。在display時,由$this->dtp->AssignSysTag()處理
 39         //如果需要面包屑導航等信息,則要new TypeLink,原理也是往Fields中在賦值
 40         if ($needtypelink) {
 41             $this->TypeLink = new TypeLink($typeid);
 42             if (is_array($this->TypeLink->TypeInfos)) {
 43                 foreach ($this->TypeLink->TypeInfos as $k=>$v) {
 44                     if (preg_match("/[^0-9]/", $k)) {
 45                         $this->Fields[$k] = $v;
 46                     }
 47                 }
 48             }
 49             $_sys_globals['curfile'] = 'partview';
 50             $_sys_globals['typename'] = $this->Fields['typename'];
 51 
 52             //設置環境變量
 53             SetSysEnv($this->TypeID, $this->Fields['typename'], 0, '', 'partview');
 54             $this->Fields['position'] = $this->TypeLink->GetPositionLink(true);
 55             $this->Fields['title'] = $this->TypeLink->GetPositionLink(false);
 56         }
 57         $this->Fields['myname']="mian_wu";
 58         //全局變量,可以通過{dede:globel.testlist}訪問到。在display時,由$this->dtp->AssignSysTag()處理
 59         $GLOBALS['testlist']=array(1,2,3,4,5);
 60        
 61 
 62         //解析框架自定義模板,arclist/channel/memeberlist.....
 63         MakeOneTag($this->dtp, $this);
 64         //解析自己定義模板,沒有自定義則此代碼不需要。
 65         foreach ($this->dtp->CTags as $tid => $ctag) {
 66             if ($ctag->GetName()=="myfield") {
 67                 //自定義單標簽
 68                 //$this->assgin() //去解析自定義模板
 69                 $this->dtp->Assign($tid, $this->Fields[$ctag->GetAtt('name')]);
 70             } elseif ($ctag->GetName()=="mytag") {
 71                 //自定義復合標簽
 72                 //自定義模板解析的兩種方式
 73                 //1.可以寫在taglib/tagName.lib.php的形式,模板會自動加載並解析。
 74                 //2.直接在CTags里面通過名字匹配到id,並assin進入值。
 75                 $this->dtp->Assign($tid, $this->Mytag($ctag->GetInnerText()));
 76             }
 77         }
 78     }
 79     public function Mytag($innertext)
 80     {
 81         //重新初始化底層解析模板。
 82         $dtp2 = new DedeTagParse();
 83         $dtp2->SetNameSpace('field', '[', ']');
 84         $dtp2->LoadSource($innertext);
 85         foreach ($dtp2->CTags as $k=>$ctag) {
 86             if ($ctag->GetName()=='myname') {
 87                 //此處賦的值,自行處理
 88                 $dtp2->Assign($k, "mian_wu");
 89             }
 90         }
 91         return $dtp2->GetResult();
 92     }
 93     public function Display()
 94     {
 95         //底層調用了$this->dtp->AssignSysTag();(global,include,foreach,var,runphp)
 96         $this->dtp->Display();
 97     }
 98 }
 99 
100 $a=new TestView(2);
101 $a->Display();
測試類

 

    
 1 <html lang="en">
 2 <head>
 3     <meta charset="UTF-8">
 4     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 5     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 6     <title>{dede:global.cfg_webname/}</title>
 7 </head>
 8 <body>
 9     {dede:foreach array="testlist"}
10      [field:key /]- [field:value /]
11      {/dede:foreach}
12 
13      <div>
14         {dede:arclist  limit='0,4' flag="p"}
15         <div class='d1arc'><a href="[field:arcurl/]">[field:title/]</a></div>
16         {/dede:arclist} </div>
17      </div>
18      {dede:field.myname /}
19      {dede:mytag}
20          [field:myname/]
21      {/dede:mytag}
22 </body>
23 </html>
測試頁面

 

 四、數據庫操作分析

  

 1    common.inc.php 核心類分析  2     1.定義全局變量
 3     2.過濾請求參數
 4     3.加載數據庫配置 require_once(DEDEDATA.'/common.inc.php');//line 152
 5     4.設置模板目錄變量
 6     5.分頁參數的設置
 7     6.自動加載類庫處理
 8     7.引入數據庫類
 9     8.全局常用函數 require_once(DEDEINC.'/common.func.php'); //在line 368,做了兼容處理,擴展的函數可以直接寫在extend.func.php中。
11     9.路由處理,請求分發
12     10.載入小助手配置
13   dedesqli.class.php 
        
        $sql="xxxx";
        $dsql->Execute('name', $sql);
        while ($row = $dsql->GetObject('name')) {
         $arr[] = $row;
        }
14     1.$dsql = $dsqli = $db = new DedeSqli(FALSE);  //line 21 在工程所有文件中均不需要單獨初始化這個類,可直接用 $dsql 或 $db 進行操作
15     2.SetQuery($sql) :會自動把SQL語句里的#@__替換為$this->dbPrefix(在配置文件中為$cfg_dbprefix)。並設置$this->queryString
16     3.Execute($id="me", $sql='') //如果sql不為空,內部會調用SetQuery,替換前綴。
18       $this->result[$id] = mysqli_query($this->linkID, $this->queryString); //line 315 執行sql返回執行結果。
19     4.GetOne($sql='',$acctype=MYSQLI_ASSOC) 
20        if(!preg_match("/LIMIT/i",$sql)) $this->SetQuery(preg_replace("/[,;]$/i", '', trim($sql))." LIMIT 0,1;");//line 351        //內部通過正則加上了limit 0,1
21        $this->Execute("one"); //line 354 調用Execute
22     5.GetArray和GetObject
function GetObject($id="me")
{
if($this->result[$id]===0)
{
return FALSE;
}
else
{
return mysqli_fetch_object($this->result[$id]);
}
}
23     6.ExecuteNoneQuery($sql='')執行一個不返回結果的SQL語句,如update,delete,insert等

  五、總結

    dedecms 就兩個核心類 dedetag.class.php、common.inc.php。一行行讀源碼,就可以知道它得工作原理。二次開發時,需要哪部分就找到對應的源碼進行分析。其它的就應該沒什么困難了。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM