首先進入 DIY 後。點擊模塊的鏈接是
- <a id="hd_mod" onclick="spaceDiy.getdiy('blockclass');this.blur();return false;" href=""> 模塊</a>
在這裏調用了 js 函數 getdiy() 並且傳進一個參數 'blockclass' ,在 portal_diy.js 中我找到了這個函數。 997 行。
其中流程執行的程序段是
- getdiy : function (type) {
- if (type) {
- var nav = $('controlnav').children;
- for (var i in nav) {
- if (nav[i].className == 'current') {
- nav[i].className = '';
- var contentid = 'content'+nav[i].id.replace('nav', '');
- if ($(contentid)) $(contentid).style.display = 'none';
- }
- }
- $('nav'+type).className = 'current';
- if (type == 'start' || type == 'frame') {
- $('content'+type).style.display = 'block';
- return true;
- }
- if(type == 'blockclass' && $('content'+type).innerHTML !='') {
- $('content'+type).style.display = 'block';
- return true;
- }
- var para = '&op='+type;
- if (arguments.length > 1) {
- for (var i = 1; i < arguments.length; i++) {
- para += '&' + arguments[i] + '=' + arguments[++i];
- }
- }
- var ajaxtarget = type == 'diy' ? 'diyimages' : '';
- var x = new Ajax();
- x.showId = ajaxtarget;
- x.get('portal.php?mod=portalcp&ac=diy'+para+'&inajax=1&ajaxtarget='+ajaxtarget,function(s, x) {
- if (s) {
- if (typeof cpb_frame == 'object' && !BROWSER.ie) {delete cpb_frame;}
- if (!$('content'+type)) {
- var dom = document.createElement('div');
- dom.id = 'content'+type;
- $('controlcontent').appendChild(dom);
- }
- $('content'+type).innerHTML = s;
- $('content'+type).style.display = 'block';
- if (type == 'diy') {
- spaceDiy.setCurrentDiy(spaceDiy.currentDiy);
- if (spaceDiy.styleSheet.rules.length > 0) {
- Util.show('recover_button');
- }
- }
- var evaled = false;
- if(s.indexOf('ajaxerror') != -1) {
- evalscript(s);
- evaled = true;
- }
- if(!evaled && (typeof ajaxerror == 'undefined' || !ajaxerror)) {
- if(x.showId) {
- ajaxupdateevents($(x.showId));
- }
- }
- if(!evaled) evalscript(s);
- }
- });
- }
- }
看到這裏我們會看到程序會請求一個地址
- http://x2/portal.php?mod=portalcp&ac=diy&op=blockclass&inajax=1&ajaxtarget=
看到這個之後,我們先放一邊,在 portalcp_diy.htm 中我們找到了生成 diy 模塊選項的這塊代碼
- <!--{loop $_G['cache']['blockclass'] $key $value}-->
- <!--{if $isfirst}-->
- <!--{eval $isfirst=0;}-->
- <ul id="contentblockclass_$key">
- <!--{else}-->
- <ul id="contentblockclass_$key" >
- <!--{/if}-->
- <li >
- <ol>
- <!--{loop $value[subs] $skey $svalue}-->
- <li
><label onmousedown="drag.createObj
(event,'block','$skey');" onmouseover="className='hover';"
onmouseout="this.className='';">$svalue[name]</label></li> - <!--{/loop}-->
- </ol>
- </li>
- </ul>
- <!--{/loop}-->
在這裏使用了 dz 中的模板語法 loop 與 /loop 間循環把 $_G['cache']['blockclass'] 中的值以 html 形式輸出。好了,我們知道了問題的上一個根源。 $_G 是 dx 中的全局變量,那我們在 dx 中把它輸出出來看看,裏面有沒有內容。在
- http://x2/portal.php?mod=portalcp&ac=diy&op=blockclass&inajax=1&ajaxtarget=
根據這個地址,找到 portal_portalcp.php,其中還包含了比較重要的一個文件是 portalcp_diy.php
其中的
- if($op == 'blockclass') {
這段對我們上面 js 中的請求進行了處理。
- loadcache('blockclass');
這段是讀取 blockclass 為名字的緩存,讀到 $_G['cache']['blockclass'] 中。説到這裏,大家應該明白這之間的關係了吧。
鼠標點擊觸發 js 函數,js 函數中 get 一個 php 文件,php 文件中對這次請求進行了處理,讀取了 blockclass 緩存,存到了 $_G['cache']['blockclass'] 中,然後在網站模板文件中把它們循環顯示出來。就是這樣。
問題分析到這裏知道了流程,那麼這個問題就出在 $_G['cache']['blockclass'] 上。我嘗試打印了 $_G['cache']['blockclass'] 的值。
- <?php
- require './source/class/class_core.php';
- $discuz = & discuz_core::instance();
- $discuz->cachelist = $cachelist;
- $discuz->init();
- loadcache('blockclass');
- print_r($_G['cache']['blockclass']);
- ?>
這段程序就是讀下 blockclass 緩存,然後把 $_G['cache']['blockclass'] 的值打出來,奇怪的是,我在這個站長的站上這個值打印出來是空的,只有結構沒有數據,所以當然顯示模塊為空了。
沒辦法,只有繼續往上查。查什麼?查讀取緩存的程序,讀取模塊緩存的函數是 blockclass_cache() 在 function_block.php 中
在這裏,我摘出了部分代碼,然後讓它輸出我需要的東西。程序代碼不在這裏貼了。上傳附件中了。
在這個函數中程序分別讀取 class/block 下面文件夾中的程序文件,輸出結果如圖:

分別把它讀取 block 模塊的文件、類、方法的步驟讀出並且顯示出來。使用這個文件,在站長的服務器上發現了問題,輸出並沒有進行完,只輸出到了一半就停
止了。卡在了一個站長安裝的 dx 模塊上。問題就在這裏了。我把在 block 文件夾中出問題的那個模塊移出 block 目錄。在看一遍。輸出都正常了。這樣更
新一遍緩存。首頁 DIY 模塊就出來了。
總結來説。這個是因為第三方的代碼植入了 dx 的緩存體系中,在 loadcache('blockclass'); 的時候。這個第三方代碼出現了問題。程序並沒有按照以往人們想象的那樣,會報錯?導致了所需要的緩存沒有進行更新導致的錯誤。