編碼炸掉的原因 Get!

前幾天重新安裝(順便升級) PHP (5.1.x) 跟 MySQL (4.1.x) 的時候,
發生了編碼炸掉的問題,以下簡單敘述我的安裝方式。

因為在 FreeBSD 裡面,可以用 ports 安裝程式,
既輕鬆又方便,而主機亦無特別需要,
故不用自行 Compile from source files。

== 稍稍講解 ports 使用的方式 ==

用 ports 裝程式,大致上都非常愉快,
只要到想要安裝的程式目錄 (如 lang/php5)
然後鍵入以下:

make install

按下 Enter 後發個呆,就裝好了 XD

安裝 ports 前,如果要確保設定無誤,
可以先下

make configure

有些 ports 會跑出選單讓您選擇,
install 完之後,再跑

make clean

即可清理工作檔案,若連下載的資料都要一併刪除,
則可選擇執行

make distclean

如此,稍等片刻後即完成清除動作。

== 講解完畢 (茶) ==

接下來,就開始重裝我的 PHP5 與 MySQL 了。

1. PHP 部分:

先用上面說過的方式,把 lang/php5 裝起來,
剩下的其他 extension 部份,就看需求下指令安裝,
大致上,在裝好 lang/php5 與 lang/php5-extensions 後,
就已足以應付大部分的使用需求了。

因為有中文字碼的一些怪問題,因此我還裝了 mbstring 模組,
如果找不到相對應的 ports 的目錄,可以在 ports 目錄下,
執行以下指令:

make search "mbstring" | more

只要 ports 的檔案有定期更新安裝,
大多數狀況下應該都會得到類似這樣的回答:

Port: php5-mbstring-5.0.5
Path: /usr/ports/converters/php5-mbstring
Info: The mbstring shared extension for php
..

查到該目錄後,下指令便可安裝;
因為 ports 的關連性都已寫在檔案中,
故在正常狀況下,使用者不需擔心有什麼東西缺裝了,
ports 會自動幫你準備好。

2. MySQL 部分:

MySQL 的安裝,下的指令跟上次我安裝的方式一樣:

make WITH_CHARSET=utf8 WITH_XCHARSET=all WITH_COLLATION=utf8_general_ci BUILD_OPTIMIZED=yes install

安裝完後,相關設定請各位稍微找一下網路,
在此不多贅述。

安裝完後,鍵入 mysql -p 指令,
輸入密碼後便可進入 MySQL 命令列模式。

成功登入後,使用

SHOW VARIABLES LIKE 'character_set_%';
SHOW VARIABLES LIKE 'collation_%';

檢查 MySQL 預設的連線與資料庫等的編碼,
而鍵入 exit; 則是離開 mysql 命令列模式。

這幾天檢查了很多地方,
後來才知道,是 MySQL 的新功能導致的。

在 MySQL 4.1.x 環境下,
會去跟發出 query 指令的連線確認編碼;
我上一版安裝的是 4.0.x,並無此功能。

而也因此,每次 PHP 發出連線請求的時候,
MySQL 會覺得它是使用 latin 字集存取資料.. Orz

解決方式:

– 修改 PHP5 的 Source code 重編
== 不過,因為很懶得看原始檔與等待編譯,所以沒有這麼做

– 修改 PHP Source 連線的部份,在建立連線之後的下一行程式,
新增 mysql_query(‘SET NAMES utf8’)
== 可是我也很懶得每支程式慢慢看慢慢改耶.. ||

經過一番搜尋,找到這樣的方式:

– 設定 my.cnf (還是 my.ini ?),在 [mysql] 下新增:
init_connect = 'SET NAMES utf8;'
== 但是我不知道為什麼都沒有成功過 囧rz

那麼,還有這麼一個方式。

– 在 rc.conf (或 rc.local) 中,啟動 MySQL daemon 的時候,
加入以下參數

--default-character-set=utf8 --skip-character-set-client-handshake

前者設定預設連線編碼為 UTF-8,後者忽略存取端的編碼設定..

“也就是說,強迫推銷 囧?”

因我的伺服器都跑 UTF-8,所以我不用擔心其他編碼問題,
再說.. UTF-8 可以容納的語言可多著哩。

舉例而言,我是在 rc.local 中載入 MySQL,
因此指令為以下一大串:

/usr/local/bin/mysqld_safe --default-character-set=utf8 \
--skip-character-set-client-handshake &

mysqld_safe 的說明是這樣寫的

o –skip-character-set-client-handshake
Ignore character set information sent by the client and use the
default server character set. This option makes MySQL 4.1 and higher
behave like MySQL 4.0.

才差了 0.1 版,就讓我暈了幾天,真是恐怖。

做完以上動作之後,理論上就應該不會出現亂碼了;
無論如何,問號大隊就此撤軍啦 XD

今天就先寫到這裡了,
廣告時間,我們開放五位名額發問,
若超過的話,就代表我的 BLOG 還滿有人看的啊 (謎)