dedecms代碼研究(1)開篇dedecms 相信大家一定都知道這個cms 系統,功能比較強大,有比較完善的內容發布,還有內容靜態化系統,還有就是它有自己獨特的標簽系統和模板系統。而模板系統也是其他cms系統比較難模仿的的東西,這個東西還是需要一點開發功力和技巧的。本系列文章就研究一下dedecms的這套系統,挖掘一下看看里面有什么好東西。建議大家先了解一下dedecms的功能。自己先動手用一下,對系統功能有個大概了解。本文先帶領大家了解一下dedecms的代碼和功能架構。其實,dedecms在架構上沒什么應用架構模式可言,就是最簡單的php 應用而已。訪問不同的PHP 文件,管理不同的系統功能。看目錄大家都能猜出來各個目錄干什么用的。include目錄放系統的一些公用函數和類,plus目錄放插件,templates目錄放模板,dede 目錄是管理后臺目錄。我們打開include 目錄,看看里面都有什么好東西。calendar 一個選時間的jscaptcha 一個驗證碼,還是開源組件code 沒啥意思,翻頁的文字data 里面是一些系統用到的資源,比如聲音,分詞庫,字體,圖片等dialog 里面估計是一些Ajax彈出窗口的內容部分。以后碰到了再說inc 里面一些單獨的功能類函數,以后研究一下為什么要單獨放payment 支付接口taglib 好東西,是dedecms的標簽存放的地方,打開看看,里面一堆文件,貌似就是dedecms的模板標簽啦tpllib 模板庫?暫時搞不明白,希望隨著研究深入,能弄明白其他 include 目錄下的文件估計都是一些最基本的功能文件啦,比如常用函數,模板系統之類的東西了。用到再說吧打開dede目錄(就是dedecms的管理目錄)看看,喲嗬,里面的東西還挺多,看名字就知道了,都是各種功能管理文件,一個功能一個文件。最原始的網站開發模式做出來的。我們姑且稱之為高效吧。畢竟PHPwind和discuz之類也是用類似的方法開發的。整個程序大體就這些東西啦。功能就不講了,建議不熟悉dedecms的朋友自己看一下dedecms的后臺管理功能,這樣能有助于我們更好理解和分析它。另外提一點,我們的這次代碼分析,主要分析的是其頁面生成、顯示、模板處理、標簽處理部分,這套系統也是dedecms比較引以為傲的東西,之后呢,還會分析一些筆者覺得比較酷的功能代碼。最后,希望這次代碼分析旅程能讓大家有所收獲。sourcejoy 之dedecms代碼研究(2)從index開始現在繼續,今天講的主要是dedecms的入口代碼。2先打開index.php看看里面是什么吧。打開根目錄下的index.php嗯,映入眼簾的是一個if語句。檢查/data/common.inc.php是否存在。如果不存在就跳轉到安裝界面。我們來到/data/看看這個目錄和common.inc.php。打開/data/,里面很多目錄和文件,有上傳的臨時目錄,模板緩存,壓縮的臨時目錄,各種數據庫里保存的系統配置信息的緩存文件以及其他的一些東西,就一個字亂~好吧,我們打開common.inc.php。哦,原來就是保存了數據庫連接的相關變量而已。說白了,就是dedecms的數據庫連接配置文件,估計是安裝完系統生成的。所以/index.php 會檢查它是否存在。我們回到/index.php中繼續往下看,第二個if語句,判斷GET請求“upcache”是否存在,存在就更新首頁緩存,不存在就直接301 跳轉到index.html,也就是dedecms的靜態首頁(記住,dedecms的前臺頁面都是系統生成的靜態頁面)。想想接下來我們要研究什么?對,就是GET請求“upcache”存在的時候,更新首頁緩存這小段代碼啦。代碼如下:require_once (dirname(__FILE__) . "/include/common.inc.php");require_once DEDEINC."/arc.partview.class.php";$GLOBALS['_arclistEnv'] = 'index';$row = $dsql->GetOne("Select * From `#@__homepageset`");$row['templet'] = MfTemplet($row['templet']);$pv = new PartView();$pv->SetTemplet($cfg_basedir . $cfg_templets_dir . "/" . $row['templet']);$pv->SaveToHtml(dirname(__FILE__).'/index.html');include(dirname(__FILE__).'/index.html');exit();先是加載/include/common.inc.php,估計是一些常用函數和加載其他系統函數和類的文件。接下來又加載了DEDEINC."/arc.partview.class.php",注意DEDEINC 這個常量,我們知道經過前期對dedecms 目錄結構觀察,arc.partview.class.php 是在/include 目錄下的,而加載/include/common.inc.php 卻沒有用DEDEINC 這個常量,這說明,common.inc.php 里面定義了DEDEINC 這個常量,所以后面得以使用,也印證了common.inc.php 大體作用就是系統運行基本部分,都在這里面啦。我們不急著進common.inc.php,繼續把index.php 的更新緩存代碼看完。第三句,設置了一個全局變量:$GLOBALS['_arclistEnv'] = 'index';第四行,獲取一個表'#@__homepageset'的所有記錄,當然如果你看下數據庫,里面沒有“#@__homepageset”這個表,我們判斷,是數據庫操作相關函數把表名用表名前綴替換了一下前半部分,這個都不重要了,重要的是,通過這句,獲取了首頁的相關配置信息,我們打開數據庫里面的dede_homepageset表,暈,就一條記錄,倆字段,基本猜到了,一個是首頁模板名稱,一個是生成的靜態文件的位置。回來繼續分析前面的代碼$row['templet'] = MfTemplet($row['templet']);通過MfTemplet函數好像把$row['templet']進行了某些轉換。我們記下MfTemplet函數,以待后面挖掘。接下來,就是new 了一個PartView 類,看這個名字,我們就知道了前面加載arc.partview.class.php 的作用啦。至于這個PartView類有什么作用,我們繼續看代碼。看了下面兩行,我想大家應該都明白啦$pv->SetTemplet($cfg_basedir . $cfg_templets_dir . "/" . $row['templet']);3$pv->SaveToHtml(dirname(__FILE__).'/index.html');創建個視圖對象(PartView類的實例,我們姑且叫視圖對象),設置模板,通過SaveToHtml方法,把最后生成的頁面寫到指定位置。首頁生成完畢,接下來就是把生成的靜態文件通過include的形式顯示出來,然后exit中斷頁面解析。至此,/index.php 就分析完啦。它先是通過/data/common.inc.php,判斷是否安裝了dedecms或者說判斷是否定義了數據庫配置信息,好為后面操作打下基礎。然后判斷是否有GET 請求"upcache",如果有就加載/include/common.inc.php 初始化系統,然后調用partview類的相關方法來生成靜態首頁文件,最后顯示出來。這么來看dedecms也沒有太多的秘密嘛~不過呢,我們這篇文章也遺留下了幾個問題:1)加載了/include/common.inc.php,里面做了哪些工作?2)/include/arc.partview.class.php到底是干什么的,/include/下還有很多arc開頭的文件都是干什么的?3)MfTemplet這個函數到底對模板文件路徑這個字符串做了什么操作?4)partview類的相關方法都有什么秘密?帶著這幾個疑問,我們將結束本文,后面的文章將將這些謎題一一揭開。sourcejoy 之dedecms代碼研究(3)partview的迷惑上次,我們從dedecms的index.php文件中了解到了很多信息,也提出了一些問題,本文開始就帶著前面的問題,繼續我們的dedecms之旅吧。先回顧一下之前我們在index.php文件研究中總結的東西。首先加載common.inc.php,接下來組織模板,生成靜態頁面并跳到靜態頁面。接下來,我們就先來看看common.inc.php 里面都有什么吧。打開/include/common.inc.php 里面的注釋已經說地比較清楚了。我們大概說說結構。先是定義一堆常量。然后是做一些安全措施,對PHP 的系統環境進行一些設置,代碼里面的注釋已經寫地很清楚了。接下來是把dedecms的系統配置參數文件包含進來:require_once(DEDEDATA."/config.cache.inc.php");看文件名字,我們猜測這個配置文件可能是數據庫里面的配置信息的緩存。接下來加載了數據庫配置信息文件:require_once(DEDEDATA.'/common.inc.php');這個文件,不是根據數據庫中信息生成的緩存,而是dedecms安裝的時候生成的。前一篇文章我們說過index.php 文件開始,檢測dedecms是否安裝,就是看這個文件是否存在的。再接下來,整理了很多目錄,比如:站點根目錄、模板目錄,插件目錄、數據目錄等,還整理了很多變量。最后加載了數據庫操作類dedesql.class.php和常用函數文件common.func.php4嗯,common.inc.php的謎底揭開,里面沒什么好玩的東西啦,都是最基本的東西。接下來我們就得看看arc.partview.class.php吧,這里面可是dedecms關鍵呢加載了channelunit.class.php,typelink.class.php,ftp.class.php下面就是partview類的定義啦因為index.php 中使用partview類的SetTemplet方法和SaveToHtml方法,所以,我們為了能更簡單地深入,就從這兩個方法著手。我們先看看partview的構造函數。創建了一個DedeTagParse類的實例,看名字是標簽解析類哦。然后設置了幾個參數。接下來,new了一個TypeLink 類,設置了一堆參數。搞的很云里霧里的。看看 SetTemplet吧。啊,這個還算簡單。先,使用DedeTagParse類的LoadTemplet方法載入模板。再,設置一些Fields數組的元素最后,調用ParseTemplet方法。ParseTemplet方法里面弄了一堆$GLOBALS 數組的元素,然后調用了MakeOneTag函數。費解啊再看看SaveToHtml方法吧,前面就是建目錄,最后用DedeTagParse的SaveTo 方法保存到文件。呃~不給力啊。只能回頭想想,都看到了什么~嗯,為了能生成首頁,搞了個很搞不懂的partview類,然后里面調用了貌似萬能的DedeTagParse方法,解析模板,生成靜態文件。僅此而已。里面還夾雜了其他函數和類,但不管怎么樣這個DedeTagParse是重點,下次得重點分析了。今天就到這吧,鳥兒的~太亂了,一點章法都沒有~sourcejoy 之dedecms代碼研究(4)繼續徘徊partview之前,我們像掉進沼澤一樣,看到無盡的變量,數組元素,莫名其面的東西擺在我們面前。今天,我們繼續艱難前行,想辦法走出partview類的泥潭。上一篇,我們胡亂分析了partview類,完全搞不懂干什么的,里面弄了一堆變量,最清晰的我們只是知道幾個生成首頁的關鍵地方調用了DedeTagParse 類的LoadTemplet 方法和SaveTo 方法。而在partview 類定義的文件頭部,包含了幾個文件,我們就避開partview,先來看看這幾個包含的文件吧。require_once(DEDEINC.'/channelunit.class.php');require_once(DEDEINC.'/typelink.class.php');require_once(DEDEINC.'/ftp.class.php');5ftp.class.php,不用說,就是ftp 相關操作類吧,我們之前看partview 代碼的時候,了解到,在生成靜態文件的時候,使用了ftp相關方法,貌似就是可以遠程寫文件滴。至于怎么操作FTP 的,其實就是封裝了php 函數庫中ftp 開頭的相關函數而已,代碼很簡單,不說了。typelink.class.php,我們也在partview 代碼里面見過的,打開看看吧。大概看了一下代碼,里面是type 的鏈接相關的東西,每個方法都聲稱一個指定type 的鏈接html 字符串。其實,我有點隱約感覺到在dedecms 中,type 就是指欄目,不知道是不是這樣。再來看看channelunit.class.php 吧。里面是 ChannelUnit 類的定義,而且我們發現,這個ChannelUnit 類沒有被使用過。所以先不去看他。我們注意到,這里面還加載了兩個文件:require_once(DEDEINC."/dedetag.class.php");require_once(DEDEINC."/channelunit.func.php");dedetag.class.php,打開看看,嗯,很復雜,但我們發現用于解析模板和生成文件的DedeTagParse 類在里面,呵呵,先記住,以后慢慢研究。channelunit.func.php 里面都什么函數呢?打開一看,嗯,一堆變量,幾個獲取這種信息的函數,在我們瀏覽過程中,發現了兩個函數:MfTemplet 和MakeOneTag我們知道,在index.php 中就用了MfTemplet 函數,回頭打開index.php 看看怎么調用的:$row['templet'] = MfTemplet($row['templet']);我們之前了解過,$row['templet']保存的是default/index.htm 這個值,就是模板文件路徑。接下來我們看看MfTemplet 函數都做了什么吧。//模板目錄規則function MfTemplet($tmpdir){$tmpdir = str_replace("{style}",$GLOBALS['cfg_df_style'],$tmpdir);$tmpdir = ereg_replace("/{1,}","/",$tmpdir);return $tmpdir;}注釋里面寫的是“模板目錄規則”,再看看代碼,哦,仿佛明白了一點兒了,就是替換模板路徑里面的{style}為全局變量$GLOBALS['cfg_df_style']中的值。應該跟使用不同模板套系有關吧。意義不是很大就不再繼續研究了。我們看另一個函數MakeOneTag,這個在partview類的ParseTemplet 方法中,此方法看名字就是解析模板,而方法的大部分代碼都是在處理變量,看不大懂干什么的,最后一句調用了MakeOneTag 函數。貌似主要解析模板就是靠這個函數了。使用如下:MakeOneTag($this->dtp,$this);第一個參數是DedeTagParse類的實力,第二個參數就是partview類實例的句柄啦。我們看看channelunit.func.php 中這個函數是干什么的吧。嗯,只能大概看,因為好多東西,我們都不清楚啊,郁悶了。這里面遍歷了/include/taglib/下所有有lib 后綴的文件,并把文件路徑加入數組,然后對DedeTagParse 類的CTag 進行了遍歷,6由于我們沒有研究DedeTagParse 類,所以這塊暫時不懂呢,不過也算小有進展了。看來還得回到partview里面去重新看看了。構造函數沒什么特別的,就是創建了DedeTagParse 類實例,進行了一些設置而已。我們知道index.php 創建partview實例后執行了SetTemplet 方法,我們再看看SetTemplet 方法吧。這里面調用了DedeTagParse類實例的LoadTemplet 方法,看來我們就得從這里入手,去抽絲剝繭啦。分析不下去了~留幾個疑問下次再說。1)DedeTagParse 類LoadTemplet 方法說開去。2)MakeOneTag 到底在搞什么。看來只有徹底先把DedeTagParse 類LoadTemplet 方法搞懂才能進一步啊,目前還是一頭霧水。sourcejoy 之dedecms代碼研究(5)從DedeTagParse開始前面,我們一直在dedecms 的外圍,被各種全局變量和各種調用所迷惑,我們抓住了一個關鍵的線索DedeTagParse 類,研究明白它,就可以弄清楚很多東西了。看看這個 NB 的DedeTagParse 類吧。嗯,先看構造函數,沒什么特別的,就是設置了一堆初始化參數。接下來就找LoadTemplet 方法吧。找到后,我們發現LoadTemplet 方法其實是指向LoadTemplate 方法的,無語啊,難道作者英文就差到此等地步?看看那個LoadTemplate 方法吧。里面先用 SetDefault 方法設置了幾個初始變量:$this->SourceString = '';$this->CTags = '';$this->Count=-1;然后判斷模板文件是否存在。然后針對不同情況對$this->SourceString 賦值,并調用$this->ParseTemplet();方法。這塊的代碼看出來,作者開發功力有待改進啊,都5.6 了,代碼重構還如此糟糕,唉~為什么不能把$this->ParseTemplet();這句放在if 外面呢?文件不存在時候,很簡單,就是把“文件不存在”這句話放到$this->SourceString 中,然后調用$this->ParseTemplet();。文件存在的時候,也很簡單,fgets 讀取文件內容(麻煩,為啥不用file_get_contents 呢),然后,又是一個if,通過$this->LoadCache($filename)返回值判斷是否有緩存,如果返回true 說明讀取到緩存的模板了,就返回空字符串(怎么可以這樣呢?返回值也太不負責了吧),如果返回false 就調用$this->ParseTemplet();重新解析模板。LoadTemplate 大致就是這些,無非是讀取模板文件內容,然后看是否有緩存,有就不解析模板,沒有就解析模板,僅此而已。我們接下來看看$this->LoadCache 方法吧,找到方法定義的部分,呀喝,代碼還不少。7先是通過$this->IsCache 判斷是否允許緩存(這個屬性是在DedeTagParse 類實例化的時候設定的,跟dede
新聞熱點
疑難解答