ホームページ制作 オフィスオバタ

PHPをShift-JISで構築した際にMYSQL保存時の文字化けを回避する

ホームページでMYSQL等のデータベースを使う場合は、PHP等でサイト構築する必要があります。

通常はHTMLもPHPもMYSQLも文字コードを「UTF-8」で構築すれば特に文字化けは発生しません。

ただ、サイトを「Shift-JIS」で構築しなければならない場合もあります。
Shift-JISでPHPを構築する場合は、文字コード変換などを行えば容易にできます。

ところが、MYSQLに保存した際に、一部の特殊文字が文字化けして保存されました。

今回Shift-JIS構築のPHPでMYSQLに文字化けの原因と対策について調べましたので、忘備録として記録いたします。

今回MYSQL保存で文字化けした文字は「髙」と「﨑」と「Ⅳ」

投稿記事をShift-JISでMYSQLに保存するアプリの作成で、何気に入力したら文字化けが発生しました。

一応phpMyadminでどのように登録されているか確認しました。

やはりというか、Shift-JISには文字化けがつきものです。
通常文字は大丈夫ですが、旧字体漢字などは文字化けします。

ちなみにPHP側でMYSQLへの文字コードセットは「CP932」なのにMYSQLで文字化け

文字コード「Shift-JIS」や「SJIS」ではPHPでも一部の文字化けが発生します。
そこで「SJIS-win」や「CP932」を指定すると、旧字体も文字化けしません。

MYSQLと接続する際には、文字コードを「CP932」にしています。
経路を調査すると、PHPの中では文字化けしていません。
MYSQLに保存した時に文字化けしています。

いったいなぜ、このMYSQLで文字化けするのでしょう?
調べてみました。

原因はMYSQLの「照合順序」指定

 原因を調べるために、phpMyadminを見ていたら、気になる部分がありました。
それがこちらです。

照合順序が「SJIS」になっていました。
データベースを新規作成した時には照合順序を「UTF-8」にしていたのですが、なぜかSJISになっていました。

照合順序がSJISになっていた原因

照合順序デフォルトがUTF-8なのになぜ「SJIS」になっていたのか?
DB登録時のSQL文を確認したら、原因が判明しました。

CREATE TABLE テーブル名
(
 テーブルの構造設定
) DEFAULT CHARSET=sjis

DEFAULT CHARSET=sjisをSQL文で宣言していました。
なるほどこれでは確かに照合順序がSJISになります。

でもここで疑問がわきました。
照合順序って、文字化けに関係するものなの?

そこで照合順序とは何なのか?
MYSQLの照合順序について調べてみました。

MYSQLの照合順序とは

照合順序というくらいなので、検索やソートなどに関連する指定のように見えます。

調べてみると、全くその通りでした。

Shift-JISのサイトなので、Shift-JISで照合するのは問題ないように思えます。
ただ、PHPでは「CP932」に設定しているので、「SJIS」では問題があるようにも思えます。

まずは試してみようと思い、照合順序を変更してみました。

照合順序をUTF-8に変更してテストしてみました。

なにはともあれ、照合順序が「SJIS」なのは問題なので、UTF-8に設定しました。
Shift-JIS構築なのに、MYSQLをUTF-8にしたのはもともとデフォルト設定にしていたからです。

照合順序が「UTF-8」に変わったのを確認して、先ほど文字化けした「髙」「﨑」「Ⅳ」を入力してみました。

こんどは、文字化けしませんでした。

ちなみに照合順序「CP932」でも試してみました。

Shift-JISなので、照合順序はUTF-8よりCP932のほうが良いと思い、CP932に設定してためしてみました。

再び「髙」「﨑」「Ⅳ」を入力してみました。

同じShift-JISでも、CP932ならば文字化けしませんでした。

照合順序文字コード指定で文字化けが起こるのはなぜ?

「髙」「﨑」「Ⅳ」といった文字は、「SJIS」には無い文字だから、不明文字として登録されます。
だから「?」に変換されます。

無い文字は表示されない。
そこまでは理解できます。

でも照合順序なのだから、文字化けとは関係ないんじゃないの?

と思いました。
あくまでもソートするための文字コードなのだから・・・。!?

とここで、MYSQLテーブルや、カラムの文字コードはどうやって設定するのだろう?
と疑問に思いました。

調べてみました。

MYSQLテーブルに文字コードを設定する方法を調べてみました。

例えばUTF-8にする場合の文字コード設定方法を調べたら、SQL文に以下のように記述するとありました。

CREATE TABLE テーブル名
(
 テーブルの構造設定
)DEFAULT CHARSET=utf8

あれ?
照合順序設定方法と同じです。

この設定をして、phpMyadminで照合順序を調べてみたところ、「utf8-general-ci」になっていました。

MYSQLのテーブル文字コード設定と照合順序の設定方法は同じ

試してみて初めて理解できました。
MYSQLでテーブルの文字コード設定と、テーブルの照合順序設定方法は同じでした。

utf8-general-ciとかutf8-unicode-ciとか、同じutf-8でもオプションのような差異がありますが、文字コードがUTF-8を指定していることには違いないということです。

なるほど、最初照合コードが「sjis-japanese-ci」であったということは、MYSQLテーブルの文字コードも「SJIS」だったということです。

だから、「髙」「﨑」「Ⅳ」といった、SJISには無い文字を入力したら「?」に変換されたのです。

なにかつっかえていたモヤモヤが解消されました。

UTF-8で構築するほうが無難なのですが、それでもShift-JISも必要。

webサイト構築でPHPやMYSQLにたずさわるほど、UTF-8が無難ということに気づきます。

実際、Shift-JISの文字化け問題にはよく悩まされます。
ではなぜShift-JISを使うの?
と言われると、答えはマイクロソフトとの相性が良いからです。

メールフォームでも、UTF-8で送信するとoutlookで受信した際に文字化けしています。
wordやexcelなどはShift-JISが採用されています。
word等からのコピーペーストを前提にしていたりすると、Shift-JISのほうが都合がよかったりします。

無論、表示はShift-JIS、保存はUTF-8という方法もあります。
PHPで文字変換すればよいだけです。

しかしながら「CP932」というSJISの拡張文字コードを知ってからは、Shift-JIS文字化け問題は極端に出会わなくなりました。

PHPとMYSQLの指定の組み合わせで文字化けすることはあります。
ただ正しく使えば存在する文字ならば文字化けしません。

使いやすい文字コードの選択で十分対応できます。

モバイルバージョンを終了