POST TIME:2017-11-13 00:00
理解織夢模板引擎有什么意義?一方面可以更好地自定義標簽。更多在于了解織夢系統,理解模板引擎是理解織夢工作原理的第一步。理解織夢會使我們寫php代碼時更順手,同時能學習一些php代碼的組織方式。
這似乎不是那么簡單,如果你只想學習自定義標簽,可以看一下“是否需要自定義標簽”和““擴展標簽””就夠了。
一解析式引擎
如果你還沒用過dedecms的標簽,先用一下,也可以看一下“dedecms網頁模板編寫”。熟悉一下memberlist這個標簽,下面會以這個標簽為例。
織夢提供的模板分析引擎有解析式和編譯式兩種,由于現在主要使用前者,這里也只討論前者。
先來寫個模板解析的hello world 程序
***root/test.php 封面php(root指的是根目錄,以下都假設dedecms被放在了網站的根目錄)
***root/test.tpl.htm 網頁模板
{tianya:my att1=1 att2='2'} [field:my/] {/tianya:my} {tianya:test att1=1 att2='2'} [field:test/] {/tianya:test}
執行root/test.php就能查看結果
由上面的例子可以看出解析式模板運作的套路:
1php文件調用網頁模板,并顯示。
2htm文件提供網頁的大體框架,等待數據來完善網頁的具體內容,稱為網頁模板。
上面的代碼就是把第一個標簽(my標簽)顯示為這是my標簽<br/>;第二個標簽顯示為這是test標簽<br/>。
上面的代碼是怎么辦妥的
更改***root/test.php如下
***root/test.tpl.htm 網頁模板
{tianya:my att1=1 att2='2'} [field:my/] {/tianya:my} {tianya:test att1=1 att2='2'} [field:test/] {/tianya:test}
可以看到$dtp對象的內部結構,其中有一個DedeTag類的數組CTags,DedeTag類的定義見root/include/ dedetag.class.php。最好不要直接用DedeTag類的字段,而用DedeTag提供的函數。比如用tag1->GetName()而不是用tag1->TagName。花一小段時間就能把DedeTag類看完,這些語法在以后自定義標簽時會有用。
再看一個例子,***root/test.php
***root/test.htm 網頁模板
{tianya:my att1=1 att2='2'} [field:my/] {/tianya:my} {tianya:test att1=1 att2='2'} [field:test/] {/tianya:test}
會發現模板解析中有四種“勢力”
在include/ DedeTagParse.class.php中定義的解析引擎類,負責讀取模板,把其中的dedecms標簽替換成具體html文本。DedeTagParse、SetNameSpace、LoadTemplate就是類里面的方法。
標簽翻譯需要一些轉換規則,lib_my就是這一類根據標簽的屬性和具體數據得出html。
待顯示的php創建編譯引擎類對象,對模板進行編譯,在Display時,echo出html文件。
htm模板,調用標簽,用html的形式寫出動態網頁的效果,屬于被翻譯的部分。Html模板主要負責界面層次,利用封裝好的標簽進行內部處理。
除了這四大勢力,還有一個勢力視圖類。include/中以arc開頭的文件都是解析引擎的視圖類。視圖類就是封裝了解析引擎類的類,僅僅加了一些函數而已。在下載的cms默認模板中,root/index.php就用了PartView這個視圖類,解析了templets/default/index.htm。五大勢力的關系如下圖。
我們現在想象一個標簽如何被解析的。我們知道,一個xml標簽有四個元素:命名空間(上面的tianya,在dedecms中是dede)、標簽名(my)、屬性(att)、InnerText(標簽之間的內容)。命名空間在SetNameSpace中指明了,標簽名由if($tag->GetName()=='my')這一句分配任務,屬性作為函數參數使用,就差InnerText的處理。
再來看看如何處理底層模板字段([field:my/]等,field是一個關鍵字,在實際應用中,常常是數據庫元組中的字段)
***root/test.php
***root/test.htm
{tianya:zoo att1=1 att2='2'} [field:name/] is a [field:animal/] {/tianya:zoo}
可見,解析底層模板和解析標簽是一樣的,只不過把底層模板當作是以field為命名空間,‘[’和‘]’為邊界的標簽而已。
接著看一下include/taglib/memberlist.lib.php,和lib_zoo很像吧。你是不是突然懂得如何定義標簽了,讀memberlist.lib.php里面的代碼,模仿,就能自定義標簽了,可參考“擴展標簽”。所以自定義標簽只用在include/taglib里加入XX.lib.php文件,里面定義lib_XX函數即可。快點去試一試。
***把root/index.php(默認模板根目錄中的)里面的
$pv->SetTemplet($cfg_basedir . $cfg_templets_dir . "/" . $row['templet']);
改成$pv->SetTemplet($cfg_basedir .'/test.htm');
在root/test.htm使用自定義標簽吧
是否需要自定義標簽
筆者剛學織夢標簽時,第一個感覺就是之夢的標簽比較抽象,不夠好用。比如說剛才的zoo的問題,我就會定義一個zoo標簽。后來才發現應該用定義頻道的方法解決,可參考“dedecms中自定義數據模型”這篇文章。另外,標簽也有一些弱點,在開發中會慢慢體會到。
上面講了五大勢力的關系、一個標簽的解析過程和如何定義標簽,回憶一下看看是否對標簽解析有了六七成的把握。解析式模板的運作還有很多細節,讀源碼是最好的學習方法。但有點難度,看自己需要的程度吧,可以跳過這一段。
***把root/index.php(默認模板根目錄中的)里面的
$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:適當地var_dump一些變量,還有用一下ctrl+F)。主要看dedetag.class.php這個文件,是織夢的核心文件,還是該看一看的。
過程大概是這樣的:new PartView()(include/ arc.partview.class中)調用了DedeTagParse(),SetNameSpace ()做了一些初始化工作。LoadTemplate() 一方面讀取網頁模板代碼,另一方面調用ParseTemplet()把網頁模板分解標簽,屬性,底層模板等,得到$pv->CTags。
Display()調用echo GetResult()的結果。GetResult()就是由分解好的標簽,屬性,底層模板等算出結果html。由于dedecms標記滿足樹形的語法規則(像html一樣),所以,計算標簽是一個遍歷樹的過程。至于每個標簽的值的計算,就調用了AssignSysTag(),它處理了global等標記。對于自定義標記,通過調用IncludeFile處理,這個函數又通過了復雜的調用,最后調用了include\helpers\channelunit.helper中的MakeOneTag()的函數。
自己整理一下吧!
二解析與網頁的上下文
后面的部分是我在寫完“關于網頁模板”后補上的,涉及到封面模板、列表模板和文檔模板,不了解的讀者可以先看看那篇文章。
通過鏈接,網頁可以在封面頁、列表頁和文檔頁間跳轉,那怎么樣在頁面中傳遞信息呢?可以用get方式。由于系統有生成功能,它會把解析的結果生成純的html頁面,不太容易看清解析的過程。不妨先不用生成功能,如在后臺添加一篇文章,在發布選項處選“僅動態瀏覽”,之后保存,預覽。看到地址欄內容形如http://localhost/plus/view.php?aid=114。
不妨細細研究這個超鏈接,首先是aid=114。aid指article id,是文章的編號。通過給出這個編號,通過XXX處理,就能得出文章的所有信息,再加上文檔模板(就像一個格式),就能的出具體的html文檔頁。類似地,還有tid(type id,欄目號)、cid(channel id,頻道/模型號)或其他。這是在上下文間傳遞的信息。
之后說說plus/view.php。打開該文件,發現里面用aid為參數,創建了一個視圖類Archives的對象(在include/arc.archives.class中定義),并調用Display函數顯示。這和根目錄/index.php用partview視圖類對象來解析模板的道理是一樣的,不過這里多附加了aid表示具體的文章(而index中的東西是通用的,不用附加上下文)。也就是說,解析封面模板、列表模板和文檔模板都有建立解析引擎對象。
另外,鏈接中對應php文件不一定是plus/view.php,顯示文檔可用plus/view.php;顯示列表可用plus/list.php。我猜測之所以會有文檔模板和列表模板差異就是來自于不同的視圖類。
之后,若在文章的發布選項處選“生成html”,就是調用視圖類的SaveToHtml函數。得到的文章鏈接形如http://localhost/a/webbase/javascript-ajax/2010/0409/114.html。
上一篇:dedecms標簽調用大全