概要
自分の作ったWebサイト上で文字化けしていたら、もちろんいろんな対処をすると思いますが、php-MySQLを使ったサイトにおいて全く文字化けしている文字は画面上に見えないけど実は内部で文字化けしてるという状況があります
あまりこのことについて書いてある情報がないようですし、私より何倍もベテランのプログラマの方が間違えていたこともあったので、ここにシェアします
「私はPHP側での文字コード設定も、MySQL側での文字コード設定も、テーブルの文字コード設定もちゃんとしてます」
という方には関係のない話です
「文字コードの設定は細かく気にしたことないけど、ちゃんと文字化けしてないことは確認したよ」
という方や
「MySQLの文字コードなんて、テーブルの文字コードをUTF8にしておけば、あとは適当で大丈夫だよ」(←実際こう言われたことがある)
という方は要注意だと思います
確認方法
my.cnfの中の[mysql]と[client]の下にそれぞれ
default-character-set=utf8
[mysqld]の下に
character_set_server=utf8
と設定してから、MySQLコマンドラインインターフェイスを使ってSELECT文で日本語のフィールドを参照してください
文字化けしていればたぶんアウトです
「日本語」という文字列が入っている場所が「日本語」となっていたりしたらまず間違いないです
たとえブラウザ上で見る限りなんの問題もなくても、内部では文字化けしていると思います
後述の理由によりphpMyAdminなどでの確認ではダメです、MySQLコマンドラインインターフェイスを使ってください
なぜ気づかないか
例えば漢字の「日」という字をUTF8でエンコードすると16進数表記で「e697a5」になります、文字コードの設定が正しくないためこれをlatin1だと解釈するとlatin1は1バイト文字なので、「e6」「97」「a5」という三文字だと認識します
具体的には「æ」「—」「¥」です
で、テーブルの文字コードがUTF8であればこの3文字をユニコード文字だと認識して、UTF8にエンコードして保存しますから「c3a6 e28094 c2a5」というふうに格納されます
バイナリエディタでMYDファイルの中身を見てみると確認することができます(MyISAM形式の場合)
ここまではいわゆる普通の文字化けですが、同じ設定のphpにおいてこのデータベースを読むとこのステップを逆にたどって結局正しい日本語が表示されてしまうのです
コマンドラインインターフェイスからも、設定によっては正しく表示されてしまいます
そうなると文字化けした文字自体を目にすることはありません
逆に言えば文字化けしていても、あまり問題がないと言えばないのですが、全ての文字が可逆的に文字化けするとも限らないでしょうし、データ量も増えますし、気持ち悪いですからなおしたほうがいいと思います
解決方法
正しく文字コードを設定してください
MySQL側の文字コード設定は普通にいろんなところに書いてあると思いますので省略します
SHOW VARIABLES LIKE 'char%';
として
Variable_name | Value |
---|---|
character_set_client | utf8 |
character_set_connection | utf8 |
character_set_database | utf8 |
character_set_filesystem | binary |
character_set_results | utf8 |
character_set_server | utf8 |
character_set_system | utf8 |
character_sets_dir | /usr/share/mysql/charsets/ |
こうなっていれば多分大丈夫でしょう
OSで使ってる文字コードによって一部違うかもしれません
PHP側の設定は以下のリンクなどを参照してください
PHPでデータベースに接続するときのまとめ
データベースの文字コード設定は上記の設定が終わったあとに作ったものであれば自然にUTF8になっていると思いますが、以前につくったもので文字コードが違う場合は
ALTER DATABASE <database_name> DEFAULT CHARACTER SET utf8;
となおしておくといいと思います
すでに文字化けしたデータが大量に入ったテーブルがある場合は、コマンド一発では直らないと思います
phpスクリプトの中でふたつデータベースの接続を用意して、間違っている設定(今までの設定)で吸い出し、正しい設定で書きこめば修正できます