どうも、コウイチです。
今回は、僕が体験した、奇妙なバグについて書きます。
MySQLに文章を登録するPHPスクリプトを作って動かしていたのですが、
何故だか文章の途中でぶった切られて登録されるのです。
「は?INSERTは特にエラーとか出てなさそうだけど・・・」
エラーもなくこんなことをやられるとは思っていなかったので、いったい何が起きているのか?
調査の結果、想像もしていなかったところでやられていることが判明しましたので、備忘録として残しておこうと思います。
犯人は絵文字
文章の途中でぶった切られて登録される原因、実は、絵文字が犯人でした。
登録する文章に絵文字が存在した途端、その絵文字以降の文字列が欠落して登録されます。
絵文字がハテナマークに化けるならまだしも、欠落は辞めてほしい。
しかも何のエラーも出さない。
こんなことがあるんだと、逆に新鮮でしたね。
それでは、絵文字の何が悪かったのでしょうか?
絵文字は4バイト文字
絵文字は4バイトコードとなり、通常のUTF-8では扱えない文字とのことでした。
ですので、カラムを4バイト文字に対応したutf8mb4に変更する必要があります。
10.1.10.7 utf8mb4 文字セット (4 バイトの UTF-8 Unicode エンコーディング)
utf8 という名前の文字セットは、文字あたり最大 3 バイトを使用し、BMP 文字だけを含みます。utf8mb4 文字セットは、文字ごとに最大 4 バイトを使用し、補助文字をサポートします。
今回は、phpmyadminで作業する方法を解説します。
utf8mb4に対応しているか確認
utf8mb4は、MySQL5.5以上で対応しています。
バージョンが分からない場合は、まず確認しましょう。
SELECT version();
で確認できます。
これからいろいろSQL文が出てきますが、phpmyadminで入力する場合は、以下のように、操作したいデータベースを選択した状態で、「SQLタブ」の入力欄に入力してくださいね。
絵文字を入れたいカラムの文字コードをutf8mb4にする
絵文字を入れたいカラムさえ、文字コードがutf8mb4になっていれば、とりあえず大丈夫です。
SQL文を実行して、カラムの文字コードを変えましょう。
変更したいカラムの文字コードがutf8であることを確認
変更したいカラムの文字コードがutf8でない場合は慎重になった方がよいでしょう。最近ではほぼutf8になっているとは思いますが、以下のSQLを実行して確認してください。
SHOW CREATE TABLE テーブル名;
これを実行すると、このテーブルを作成するためのCREATE TABLE文が表示されます。
そこでテーブルのデフォルト文字コードが「DEFAULT CHARSET=utf8」となっていればOKです。
または、テーブルのデフォルト文字コードと違う文字コードがカラムに対して設定されている場合、そのカラムの行に文字コードが表示されているはずなので、そこがutf8になっているかを見てください。
utf8mb4はutf8の拡張版なので、utf8⇒utf8mb4に変更するにあたって格納されたデータに影響はありません。
カラムの文字コードをutf8mb4に変更
あるカラム(text型)をの文字コードをutf8⇒utf8mb4に変更する例です。
ALTER TABLE テーブル名 modify カラム名 text CHARACTER SET utf8mb4;
カラムの文字コードがutf8mb4に変更できたか確認
カラムの文字コードがutf8mb4に変更できたか確認するには、
先ほどと同様に
SHOW CREATE TABLE テーブル名;
で確認できます。
クライアント側の文字コードもutf8mb4に変更する。
クライアント側の文字コードもutf8mb4に変更しなければ、サーバ側と食い違い、文字化けの原因になりますので、必ず変更します。
具体的には
$dbh->query(‘SET NAMES utf8’);
のような、データベースへの接続文字コードを指定している個所を
$dbh->query(‘SET NAMES utf8mb4‘);
に変更しましょう。
(おまけ1)テーブルのデフォルト文字コードを変えておく
ちなみに、テーブルのデフォルト文字コードを変えておくことで、今後このテーブルに新しいカラムを追加する場合、デフォルトで文字コードがutf8mb4になります。
ALTER TABLE テーブル名 DEFAULT CHARACTER SET utf8mb4;
あくまで今後新しく追加するカラムに対してなので、既存のカラムは先ほど紹介したSQLで文字コードを変えてください。
確認方法
SHOW CREATE TABLE テーブル名;
先ほどと同様に確認します。
そこで「DEFAULT CHARSET=utf8mb4」となっていればOKです。
(おまけ2)データベースのデフォルト文字コードを変えておく
データベースの文字コードを変える場合は
ALTER DATABASE データベース名 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
となります。
これも同様に、今後このデータベースにテーブルを作成した場合、デフォルトでテーブルの文字コードがutf8mb4になるということです。
確認方法
INFOMATION_SCHEMAテーブルのSCHEMATAをチェックしてください。
まとめ
データベースのデフォルト文字コードを変えれば、テーブル作成時にその文字コードで作られるし、テーブルのデフォルト文字コードを変えれば、カラム作成時にその文字コードで作られるようになるという具合。
今回の問題の解決策としてはカラムの文字コードをutf8mb4に変えるだけでよいのだけど、最近はスマホがあるので、絵文字のような4バイトの特殊文字が簡単に入力されてしまいますね。
utf8mb4はutf8の拡張版なので、このような問題を引き起こさないためにも、全部utf8mb4にしとくのが良いかと思います。
ではまた。
コメント