MySQL+DB+OSS

MySQL・Data Base・Open Source Software

PHP と SHIFT_JIS と MySQL

2006-08-21 11:23:36 | MySQL
HTMLのmeta内charsetがSHIFT_JISであったり
CGIスクリプトがSHIFT_JISであったり
DBがSHIFT_JISであったりとどこかにSHIFT_JISが絡んでいると必ず5C問題に引っかかります。
MYSQLがUJIS(EUC-JP)でもPHPソースがEUC-JPでもぶち当たります。
SHIFT_JISがどこかに挟まっていたらハマります。
じゃあSHIFT_JISを使わなければいいだけやんという方はそれが一番手っ取り早いです。
なのでUTF8かEUC-JP(UJIS)を使っておくのが一番です。

でも、SHIFT_JISをつかっても問題ない方法に興味があるので調べてみました。


5C問題とはなにか?
SHIFT_JISで文字コードの最後に5Cがつく文字が40種類あるのですが
その文字を内部処理をする時、5Cがエスケープ文字として受け止められます。

PHPの場合、php.ini内に「Magic Quotes GPC」というオプションがあります。
これはデフォルトでONになっています。
こいつが何をするかといえば、自動でエスケープ文字を取り除くんです。
OFFにしておけばPHP内で害はないのですが、i-modeサイトを作りたい場合や、MYSQLに検索かけに行く場合などはまた変換かかってエスケープされますので同じです。
URLのエンコード/デコード時にもこの問題がでるはずです。

たとえば「ソ」は「83 5C」です。
Magic Quotes GPCをONのまま「ソ」で検索しようとしたら5Cが取り除かれて「83」だけで検索にいきます。
もちろん「83」な文字はないのでヒット件数はゼロです。

SHIFT_JISの「ソ」をきちんと「ソ」として認識してもらうには「ソ¥¥」と打てば
一番最後¥のだけがエスケープされるので「ソ」と認識してもらえます。

では、PHPでどうやればいいかというと以下のようにします。

get_magic_quotes_gpc()はget_magic_quotes_gpcの値が何で設定されているかを取得してくれる標準関数です。
「find_word」という名前で画面内のテキストボックスからある値を取得するとします。
addslashes()はエスケープ文字を追加してくれる関数です。

if (!get_magic_quotes_gpc()) {
 $find_word = (($_POST['find_word']));
} else {
 $find_word = (addslashes($_POST['find_word']));
}


addslashesを入れるだけで回避方法は単純な事なのですが、
PHPの理屈がわかっていなかったので非常に難しかったです。


5C文字は「ソ」以外にもあります。以下の40文字です。
SHIFT_JISを使っている場合、一見普通に動いているようにみえても
以下の文字を使ったときに正常な結果が得られないのなら5C問題が解決されていないという事になります。

― ソ Ы 噂 浬 欺 圭 構 蚕 十 申 曾 箪 貼 能 表 暴 予 禄
兔 喀 媾 彌 拿 杤 歃 濬 畚 秉 綵 臀 藹 觸 軆 鐔 饅 鷭


以下のサイトが非常に役に立ちました。
http://www.shtml.jp/mojibake/sjis_cgi.html

ニコヤーコさんのところでも5C問題記事発見。
http://blogs.yahoo.co.jp/mysql/13630369.html