這是一個與 WordPress 插件 bug 奮鬥的流水帳,有興趣的人再看看就好,其他人就可以直接跳過啦!
話說這幾天逛了好幾個 WordPress 相關網站,順便更新了幾個我自己站上的 plugin,也寫了兩個新的功能進去。就在一切即將大功告成的時候,熊熊發現 Firefox 的 Html Validator 套件給了我一個沒看過的錯誤圖示。
先解釋一下 Html Validator 的幾種可能檢測情況吧!最好的情況是沒有錯誤與警告,此時會給出一個綠色的勾勾圖示;如果只有警告(warning)的話,則出現黃色的驚嘆號;如果有錯誤(error)的話,則會出現紅色的 X。而這次,檢測結果出現的是一個藍紫色的 A(1 warning),但是檢視原始碼的時候,卻又告訴我沒有問題,真是奇怪……
問了一下朋友,才知道原來那個圖是代表的意思是,網頁中有無法正確解讀的字元存在,並且可用 W3C 的 The 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)文字的動作?那往往就是問題的關鍵所在喔!
可否請教一下,我用的 Get Recent Comments 外掛,也會切中文導致 validator 說有錯誤。不知道該改什麼地方才能避開這個問題?
另外是您的 meta 裏列出了文章與回應的篇數,不知道這是用哪個 tag 還是 plugin 做成的,我前一陣子找了好久都找不到。
謝謝您。
評論由 Hemiola 發表 @ 四月 29 日, 2006 3:39 下午
我已經放棄 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,晚點我再寫個簡介。
評論由 C.H.Weng 發表 @ 四月 29 日, 2006 4:52 下午
謝謝,試了的確有用。
評論由 Hemiola 發表 @ 四月 29 日, 2006 9:33 下午
關於文章與回應篇數的用法,請參考這邊:
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/
評論由 C.H.Weng 發表 @ 四月 29 日, 2006 10:37 下午
我將您的函數做了一點小修正:
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);
}
大概是這樣。
評論由 Hemiola 發表 @ 五月 7 日, 2006 6:16 上午
謝謝!
其實我到現在還是沒搞懂 UTF-8 字元的結構,所以也不知道到底該怎麼處理才完美。
不過這個 function 就先收下啦!感謝:D
對了,如果 server 有支援 mbstring 的話,用 mb_substr 來處理應該是目前所知最完美的方法。
可以參考一下 WordPress plugin - Recent Comments and Trackbacks 的討論。
評論由 C.H.Weng 發表 @ 五月 7 日, 2006 7:07 上午
想請教一下,
若要使用Sidebar Widgets這個PLUGIN,
也常常會遇到字碼切割的問題而導致整個內容消失,
如果想加入字碼檢查的話,
應該加在哪邊呢?
可否請前輩告知一下。
此外想問一下Sidebar Widgets的資料都是存在哪邊?
翻遍了資料庫跟檔案,
完全沒有看到啊@@
評論由 Caeru 發表 @ 七月 6 日, 2006 10:33 下午
Sidebar Widgets 的檔案應該都是放在 plugins 資料夾下或是其下的 widgets 資料夾下,還是你說的資料是另有所指?
要修正字碼切割的問題,首先你的伺服器必須有開啟 mbstring 這個 extension,
接下來你可以參考這個網頁:Multi-Byte String Functions,裡面的 Functions to be overloaded 一段有說到一些替代用的函式。請將 plugins 檔案中的函式名稱逐一替代掉就好了。
如果還有問題,歡迎再留言來討論。
評論由 C.H.Weng 發表 @ 七月 7 日, 2006 12:13 下午