花魁直播高品质美女在线视频互动社区 - 花魁直播官方版

 歡迎來到素材無憂網(wǎng),按 + 收藏我們
登錄 注冊 退出 找回密碼

淺談dedecms模板引擎工作原理及自定義標(biāo)簽

時間: 2020-08-20 14:32 閱讀: 作者:素材無憂網(wǎng)

理解引擎有什么意義?一方面可以更好地自定義標(biāo)簽。更多在于了解織夢系統(tǒng),理解模板引擎是理解織夢工作原理的第一步。理解織夢會使我們寫php代碼時更順手,同時能學(xué)習(xí)一些php代碼的組織方式。

這似乎不是那么簡單,如果你只想學(xué)習(xí)自定義標(biāo)簽,可以看一下“是否需要自定義標(biāo)簽”和““擴展標(biāo)簽””就夠了。

一解析式引擎

如果你還沒用過dedecms的標(biāo)簽,先用一下,也可以看一下“dedecms網(wǎng)頁模板編寫”。熟悉一下memberlist這個標(biāo)簽,下面會以這個標(biāo)簽為例。

織夢提供的模板分析引擎有解析式和編譯式兩種,由于現(xiàn)在主要使用前者,這里也只討論前者。
 

先來寫個模板解析的hello world 程序

***root/test.php  封面php(root指的是根目錄,以下都假設(shè)dedecms被放在了網(wǎng)站的根目錄)
 

<?php     require_once (dirname(__file__).'/include/common.inc.php');     //利用解析式模板所需的文件     require_once (dirname(__file__).'/include/dedetag.class.php');   //生成解析模板引擎類對象 $dtp=new DedeTagParse(); //設(shè)置命名空間,由于下面的標(biāo)簽用tianya命名空間,所以要設(shè)置一下。 $dtp->SetNameSpace('tianya'); $dtp->LoadTemplate(dirname(__file__).' est.tpl.htm ');   //把標(biāo)簽替換成具體的值 foreach ($dtp->CTags as $id=>$tag) {     if($tag->GetName()=='my')         //把id為$id的tag翻譯成這是my標(biāo)簽<br/>         $dtp->Assign($id,'這是my標(biāo)簽<br/>');         else if($tag->GetName()=='test')         $dtp->Assign($id,'這是test標(biāo)簽<br/>'); }   //把解析好的html文本echo出來 $dtp->Display();  ?>


***root/test.tpl.htm 網(wǎng)頁模板

    {tianya:my att1=1 att2='2'}
        [field:my/]
    {/tianya:my}
    {tianya:test att1=1 att2='2'}
        [field:test/]
    {/tianya:test}


執(zhí)行root/test.php就能查看結(jié)果

由上面的例子可以看出解析式模板運作的套路:

1php文件調(diào)用網(wǎng)頁模板,并顯示。

2htm文件提供網(wǎng)頁的大體框架,等待數(shù)據(jù)來完善網(wǎng)頁的具體內(nèi)容,稱為網(wǎng)頁模板。

上面的代碼就是把第一個標(biāo)簽(my標(biāo)簽)顯示為這是my標(biāo)簽<br/>;第二個標(biāo)簽顯示為這是test標(biāo)簽<br/>。

 

上面的代碼是怎么辦妥的

更改***root/test.php如下

<?php     require_once (dirname(__file__).'/include/common.inc.php');     //利用解析式模板所需的文件     require_once (dirname(__file__).'/include/dedetag.class.php');   $dtp=new DedeTagParse(); //設(shè)置命名空間,由于下面的標(biāo)簽用tianya命名空間,所以要設(shè)置一下。 $dtp->SetNameSpace('tianya'); $dtp->LoadTemplate(dirname(__file__).' est.tpl.htm '); var_dump($dtp);    //這是查看解析結(jié)果的重要方法 ?>

***root/test.tpl.htm 網(wǎng)頁模板

    {tianya:my att1=1 att2='2'}
        [field:my/]
    {/tianya:my}
    {tianya:test att1=1 att2='2'}
        [field:test/]
    {/tianya:test}

可以看到$dtp對象的內(nèi)部結(jié)構(gòu),其中有一個DedeTag類的數(shù)組CTags,DedeTag類的定義見root/include/ dedetag.class.php。最好不要直接用DedeTag類的字段,而用DedeTag提供的函數(shù)。比如用tag1->GetName()而不是用tag1->TagName?;ㄒ恍《螘r間就能把DedeTag類看完,這些語法在以后自定義標(biāo)簽時會有用。

再看一個例子,***root/test.php
 

<?php     require_once (dirname(__file__).'/include/common.inc.php');     require_once (dirname(__file__).'/include/dedetag.class.php');   function lib_my($att1,$att2) {         return '這是my標(biāo)簽<br/>屬性值'.$att1.$att2.'<br/>'; }   $dtp=new DedeTagParse(); $dtp->SetNameSpace('tianya'); $dtp->LoadTemplate(dirname(__file__).' est.tpl.htm');   foreach ($dtp->CTags as $id=>$tag) {     if($tag->GetName()=='my')     $dtp->Assign($id , lib_my($tag->GetAtt('att1'),$tag->GetAtt('att2'))); }   $dtp->Display();  ?>

***root/test.htm 網(wǎng)頁模板

    {tianya:my att1=1 att2='2'}
        [field:my/]
    {/tianya:my}
    {tianya:test att1=1 att2='2'}
        [field:test/]
    {/tianya:test}

會發(fā)現(xiàn)模板解析中有四種“勢力”

在include/ DedeTagParse.class.php中定義的解析引擎類,負(fù)責(zé)讀取模板,把其中的dedecms標(biāo)簽替換成具體html文本。DedeTagParse、SetNameSpace、LoadTemplate就是類里面的方法。

標(biāo)簽翻譯需要一些轉(zhuǎn)換規(guī)則,lib_my就是這一類根據(jù)標(biāo)簽的屬性和具體數(shù)據(jù)得出html。

待顯示的php創(chuàng)建編譯引擎類對象,對模板進行編譯,在Display時,echo出html文件。

htm模板,調(diào)用標(biāo)簽,用html的形式寫出動態(tài)網(wǎng)頁的效果,屬于被翻譯的部分。Html模板主要負(fù)責(zé)界面層次,利用封裝好的標(biāo)簽進行內(nèi)部處理。

 

除了這四大勢力,還有一個勢力視圖類。include/中以arc開頭的文件都是解析引擎的視圖類。視圖類就是封裝了解析引擎類的類,僅僅加了一些函數(shù)而已。在下載的cms默認(rèn)模板中,root/index.php就用了PartView這個視圖類,解析了templets/default/index.htm。五大勢力的關(guān)系如下圖。

淺談dedecms模板引擎工作原理及自定義標(biāo)簽(圖1)

我們現(xiàn)在想象一個標(biāo)簽如何被解析的。我們知道,一個xml標(biāo)簽有四個元素:命名空間(上面的tianya,在dedecms中是dede)、標(biāo)簽名(my)、屬性(att)、InnerText(標(biāo)簽之間的內(nèi)容)。命名空間在SetNameSpace中指明了,標(biāo)簽名由if($tag->GetName()=='my')這一句分配任務(wù),屬性作為函數(shù)參數(shù)使用,就差I(lǐng)nnerText的處理。

 

再來看看如何處理底層模板字段([field:my/]等,field是一個關(guān)鍵字,在實際應(yīng)用中,常常是數(shù)據(jù)庫元組中的字段)

***root/test.php
 

<?php     require_once (dirname(__file__).'/include/common.inc.php');     require_once (dirname(__file__).'/include/dedetag.class.php');   //看完后面的代碼再來看這個函數(shù) function lib_zoo(&$ctag) {         //還記得剛才$dtp->CTags的結(jié)構(gòu)嗎?這里把$ctag作為參數(shù)傳遞,lib__zoo外面的代碼就不用涉及太多的標(biāo)簽處理了     $reval='這是my標(biāo)簽<br/>屬性值'. $ctag->GetAtt('att1').$ctag->GetAtt('att2').'<br/>'; $innerText = $ctag->GetInnerText();   //底層模板字段的結(jié)構(gòu)都形如[field:XX]這里把它看作以field為命名空間,[]為分隔符的標(biāo)簽。     $dtp=new DedeTagParse();     $dtp->SetNameSpace('field','[',']');     $dtp->LoadSource($innerText);       //不妨把$row想想成從數(shù)據(jù)庫中讀取出來的出來的數(shù)據(jù)     $row[‘name’]= 'Snoopy';     $row[‘animal’]= 'dog';          //把標(biāo)簽替換成具體的值     foreach ($dtp->CTags as $id=>$tag)     {         if($tag->GetName()=='name')             $dtp->Assign($id, $row[‘name’]);         else if($tag->GetName()=='animal')             $dtp->Assign($id, $row[‘animal’]);     }     $reval.=$dtp->GetResult().'<br/>';     return $reval; }   $dtp=new DedeTagParse(); $dtp->SetNameSpace('tianya'); $dtp->LoadTemplate(dirname(__file__).' est.htm');   foreach ($dtp->CTags as $id=>$tag) {     if($tag->GetName()=='zoo')     $dtp->Assign($id, lib_zoo($tag)); }   $dtp->Display();  ?>


***root/test.htm

{tianya:zoo att1=1 att2='2'}
     [field:name/] is a [field:animal/]
{/tianya:zoo}

可見,解析底層模板和解析標(biāo)簽是一樣的,只不過把底層模板當(dāng)作是以field為命名空間,‘[’和‘]’為邊界的標(biāo)簽而已。

 

接著看一下include/taglib/memberlist.lib.php,和lib_zoo很像吧。你是不是突然懂得如何定義標(biāo)簽了,讀memberlist.lib.php里面的代碼,模仿,就能自定義標(biāo)簽了,可參考“擴展標(biāo)簽”。所以自定義標(biāo)簽只用在include/taglib里加入XX.lib.php文件,里面定義lib_XX函數(shù)即可。快點去試一試。

***把root/index.php(默認(rèn)模板根目錄中的)里面的

$pv->SetTemplet($cfg_basedir . $cfg_templets_dir . "/" . $row['templet']);

改成$pv->SetTemplet($cfg_basedir .'/test.htm');

在root/test.htm使用自定義標(biāo)簽吧

是否需要自定義標(biāo)簽

筆者剛學(xué)織夢標(biāo)簽時,第一個感覺就是之夢的標(biāo)簽比較抽象,不夠好用。比如說剛才的zoo的問題,我就會定義一個zoo標(biāo)簽。后來才發(fā)現(xiàn)應(yīng)該用定義頻道的方法解決,可參考“dedecms中自定義數(shù)據(jù)模型”這篇文章。另外,標(biāo)簽也有一些弱點,在開發(fā)中會慢慢體會到。

 

上面講了五大勢力的關(guān)系、一個標(biāo)簽的解析過程和如何定義標(biāo)簽,回憶一下看看是否對標(biāo)簽解析有了六七成的把握。解析式模板的運作還有很多細(xì)節(jié),讀源碼是最好的學(xué)習(xí)方法。但有點難度,看自己需要的程度吧,可以跳過這一段。

***把root/index.php(默認(rèn)模板根目錄中的)里面的

$pv->SetTemplet($cfg_basedir . $cfg_templets_dir . "/" . $row['templet']);

改成$pv->SetTemplet($cfg_basedir .'/test.htm');

編寫root/test.htm

{dede:memberlist row=6 signlen=30} 
<li><a href="[field:spaceurl/]" target="_blank">[field:uname/]</a></li>
{/dede:memberlist}

運行index.php

這是怎么辦到的,跟蹤代碼自己想吧(tips:適當(dāng)?shù)豽ar_dump一些變量,還有用一下ctrl+F)。主要看dedetag.class.php這個文件,是織夢的核心文件,還是該看一看的。

過程大概是這樣的:new PartView()(include/ arc.partview.class中)調(diào)用了DedeTagParse(),SetNameSpace ()做了一些初始化工作。LoadTemplate() 一方面讀取網(wǎng)頁模板代碼,另一方面調(diào)用ParseTemplet()把網(wǎng)頁模板分解標(biāo)簽,屬性,底層模板等,得到$pv->CTags。

Display()調(diào)用echo GetResult()的結(jié)果。GetResult()就是由分解好的標(biāo)簽,屬性,底層模板等算出結(jié)果html。由于dedecms標(biāo)記滿足樹形的語法規(guī)則(像html一樣),所以,計算標(biāo)簽是一個遍歷樹的過程。至于每個標(biāo)簽的值的計算,就調(diào)用了AssignSysTag(),它處理了global等標(biāo)記。對于自定義標(biāo)記,通過調(diào)用IncludeFile處理,這個函數(shù)又通過了復(fù)雜的調(diào)用,最后調(diào)用了includehelperschannelunit.helper中的MakeOneTag()的函數(shù)。

自己整理一下吧!

 

二 解析與網(wǎng)頁的上下文

       后面的部分是我在寫完“關(guān)于網(wǎng)頁模板”后補上的,涉及到封面模板、列表模板和文檔模板,不了解的讀者可以先看看那篇文章。

       通過鏈接,網(wǎng)頁可以在封面頁、列表頁和文檔頁間跳轉(zhuǎn),那怎么樣在頁面中傳遞信息呢?可以用get方式。由于系統(tǒng)有生成功能,它會把解析的結(jié)果生成純的html頁面,不太容易看清解析的過程。不妨先不用生成功能,如在后臺添加一篇文章,在發(fā)布選項處選“僅動態(tài)瀏覽”,之后保存,預(yù)覽??吹降刂窓趦?nèi)容形如http://localhost/plus/view.php?aid=114。

       不妨細(xì)細(xì)研究這個超鏈接,首先是aid=114。aid指article id,是文章的編號。通過給出這個編號,通過XXX處理,就能得出文章的所有信息,再加上文檔模板(就像一個格式),就能的出具體的html文檔頁。類似地,還有tid(type id,欄目號)、cid(channel id,頻道/模型號)或其他。這是在上下文間傳遞的信息。

  之后說說plus/view.php。打開該文件,發(fā)現(xiàn)里面用aid為參數(shù),創(chuàng)建了一個視圖類Archives的對象(在include/arc.archives.class中定義),并調(diào)用Display函數(shù)顯示。這和根目錄/index.php用partview視圖類對象來解析模板的道理是一樣的,不過這里多附加了aid表示具體的文章(而index中的東西是通用的,不用附加上下文)。也就是說,解析封面模板、列表模板和文檔模板都有建立解析引擎對象。

  另外,鏈接中對應(yīng)php文件不一定是plus/view.php,顯示文檔可用plus/view.php;顯示列表可用plus/list.php。我猜測之所以會有文檔模板和列表模板差異就是來自于不同的視圖類。

  之后,若在文章的發(fā)布選項處選“生成html”,就是調(diào)用視圖類的SaveToHtml函數(shù)。得到的文章鏈接形如http://localhost/a/webbase/javascript-ajax/2010/0409/114.html。


版權(quán)聲明: 本站資源均來自互聯(lián)網(wǎng)或會員發(fā)布,如果侵犯了您的權(quán)益請與我們聯(lián)系,我們將在24小時內(nèi)刪除!謝謝!

轉(zhuǎn)載請注明: 淺談dedecms模板引擎工作原理及自定義標(biāo)簽

標(biāo)簽:  
相關(guān)文章
模板推薦