用 Google 搜尋:

無聊人的無聊故事

四月 24 日, 2006

一個 WordPress plugin 的 debug 過程

文章類別:WordPress 相關, 電腦相關 — by C.H.Weng @ 8:30 下午

這是一個與 WordPress 插件 bug 奮鬥的流水帳,有興趣的人再看看就好,其他人就可以直接跳過啦!

話說這幾天逛了好幾個 WordPress 相關網站,順便更新了幾個我自己站上的 plugin,也寫了兩個新的功能進去。就在一切即將大功告成的時候,熊熊發現 Firefox 的 Html Validator 套件給了我一個沒看過的錯誤圖示。

先解釋一下 Html Validator 的幾種可能檢測情況吧!最好的情況是沒有錯誤與警告,此時會給出一個綠色的勾勾圖示;如果只有警告(warning)的話,則出現黃色的驚嘆號;如果有錯誤(error)的話,則會出現紅色的 X。而這次,檢測結果出現的是一個藍紫色的 A(1 warning),但是檢視原始碼的時候,卻又告訴我沒有問題,真是奇怪……

問了一下朋友,才知道原來那個圖是代表的意思是,網頁中有無法正確解讀的字元存在,並且可用 W3CThe W3C Markup Validation Service 來指出錯誤是發生在哪一行。

前往檢查之後,又發現一個奇怪的現象:如果我直接把網址餵給 W3C 來檢查,會指出哪一行有無法解讀的字元存在,但如果我由自己的電腦開啟網頁,再將原始碼複製給 W3C 檢查,卻又可以通過檢測。

因為我的網頁每次都有些許的不同,所以直接餵給 W3C 所指出的行數,不一定會與我自己從瀏覽器取得的原始碼符合,而且就算真的從原始碼中找相對應的行數,也沒有發現什麼異常的情況,更何況這份原始碼複製給 W3C,一樣還是可以通過檢測的啊!那麼這個奇怪的字元究竟是怎麼出現的呢?為了抓出這個傢伙,一時間還真沒有想到什麼比較好的方法……

經過一天的沉澱,終於想到一個應該可行的方法,就是用 php 的 curl 函式,直接將網頁內容擷取下來,而不透過複製的方式來取得原始碼。果然!將使用這個方法擷取的原始碼餵給 W3C,一樣會指出某一行出現編碼錯誤的訊息。再去查看相對應的行數,果然被我找到問題所在了!雖然還是沒有看到那個神秘字元長什麼樣子,不過總算稍微有點頭緒。

問題的關鍵,就出在 Random Posts for Chinese 這個 plugin 上。因為這個插件會去切割文字內容,來達到摘要的效果。也許就是在切割的過程中出了點差錯……

看了一下 code 後,果不期然,終於發現問題所在,果然是在字元切割上的問題!抓到問題來源後,稍微修改一下 code 然後正式上線……賓果!一切正常了!

Yan Feng 前輩提供的另一個插件 - Comment Hacks 中,就有一個 utf8_trim 函式,可用來處理切割 UTF-8 字元的問題。不過顯然他忘了把這功能也加到 Random Posts for Chinese 中,所以才會出現這樣的異常情況。

其實這個問題,在使用多字元文字(以亞洲國家中日韓為主)的網頁中還滿常發現的,但偏偏大多數的 WordPress plugin 作者多是使用單字元文字的歐美人士,通常都沒有注意到這個問題。因此同樣的情況很可能一再重複發生,必須靠自己來修正這些套件,才能盡量避開這些錯誤。

以上報告完畢,如果你的 WordPress 部落格老是因為這個原因通不過檢測的話,不妨檢查一下所使用的 plugin 中,是否有做切割(strip)文字的動作?那往往就是問題的關鍵所在喔!

共有 8 條評論

  1. 可否請教一下,我用的 Get Recent Comments 外掛,也會切中文導致 validator 說有錯誤。不知道該改什麼地方才能避開這個問題?

    另外是您的 meta 裏列出了文章與回應的篇數,不知道這是用哪個 tag 還是 plugin 做成的,我前一陣子找了好久都找不到。

    謝謝您。

  2. 我已經放棄 Get Recent Comments 這個 plugin 了,雖然功能好像比較多,不過對中文的支援能力真的不太好……

    我剛剛重新換回這個 plugin 試了一下,發現不一定會出現你所說的狀況,所以我只能猜測一下可能發生問題的地方,至於有沒有效,可能要請你自己改改看囉!

    首先當然是先開啟 get-recent-comments.php 這個檔案,
    然後在程式的最後一行(應該是 add_action('admin_menu', 'kjgrc_add_options_page');)前面加入這個 function:

    function utf8_trim($str) {
    $len = strlen($str);
    for ($i=strlen($str)-1; $i>=0; $i-=1) {
    $hex .= ' '.ord($str[$i]);
    $ch = ord($str[$i]);
    if (($ch & 128)==0) return(substr($str,0,$i));
    if (($ch & 192)==192) return(substr($str,0,$i));
    }
    return($str.$hex);
    }

    接下來搜尋“$text = $text . "...";”這行,
    把他替代為“$text = utf8_trim($text) . "...";”,
    然後存檔跑跑看吧!

    對了,上面的...會被取代成全型的符號,請自己改一下再搜尋喔!

    如果只是單純要顯示評論的話,我現在改用上文推薦的 Comment Hacks,建議參考看看。

    至於顯示文章與回應篇數的功能,是我自己寫的簡單 plugin,晚點我再寫個簡介。

  3. 謝謝,試了的確有用。

  4. 關於文章與回應篇數的用法,請參考這邊:

    http://www.chweng.idv.tw/blog/wordpress/comments-status/
    http://www.chweng.idv.tw/blog/wordpress/pages-status/
    http://www.chweng.idv.tw/blog/wordpress/posts-status/

  5. 我將您的函數做了一點小修正:

    function utf8_trim($str) {
    $len = strlen($str);
    if ( ( ord($str[$len-1]) & 128 ) ==0 ) return($str);

    for ($i=strlen($str)-1; $i>=0; $i-=1) {
    $hex .= ' '.ord($str[$i]);
    $ch = ord($str[$i]);
    //if (($ch & 128)==0) return(substr($str,0,$i));
    if (($ch & 192)==192) return(substr($str,0,$i));
    }

    return($str.$hex);
    }

    大概是這樣。

  6. 謝謝!

    其實我到現在還是沒搞懂 UTF-8 字元的結構,所以也不知道到底該怎麼處理才完美。
    不過這個 function 就先收下啦!感謝:D

    對了,如果 server 有支援 mbstring 的話,用 mb_substr 來處理應該是目前所知最完美的方法。
    可以參考一下 WordPress plugin - Recent Comments and Trackbacks 的討論。

  7. 想請教一下,
    若要使用Sidebar Widgets這個PLUGIN,
    也常常會遇到字碼切割的問題而導致整個內容消失,
    如果想加入字碼檢查的話,
    應該加在哪邊呢?
    可否請前輩告知一下。

    此外想問一下Sidebar Widgets的資料都是存在哪邊?
    翻遍了資料庫跟檔案,
    完全沒有看到啊@@

  8. Sidebar Widgets 的檔案應該都是放在 plugins 資料夾下或是其下的 widgets 資料夾下,還是你說的資料是另有所指?

    要修正字碼切割的問題,首先你的伺服器必須有開啟 mbstring 這個 extension,
    接下來你可以參考這個網頁:Multi-Byte String Functions,裡面的 Functions to be overloaded 一段有說到一些替代用的函式。請將 plugins 檔案中的函式名稱逐一替代掉就好了。

    如果還有問題,歡迎再留言來討論。

發表評論

(必須輸入。)
(必須輸入,但不會公開。)
(選擇性輸入、公開資訊。)

不可以 使用 HTML 標籤;你 可以 使用 BBCode 標籤。
目前支援的標籤: b color email i img size strong u url。

Comment Preview
↑Meta↑
↑Authors↑
↓Search↓
↑Categories↑
↑Recent Posts↑
↓Most Popular Posts↓
↑Recent Comments↑
↓Recent Trackbacks↓
↓Archives↓
↓Themes↓
Powered by WordPress™
Valid RSS & Atom Feed