アラカン"BOKU"のITな日常

文系システムエンジニアの”BOKU”が勉強したこと、経験したこと、日々思うことを書いてます。

PHP+MariaDB。日本語を正しく使うベストプラクティス。3つのポイントを整理する(備忘)

PHPMariaDBMySQL)との組み合わせはよくあります。

f:id:arakan_no_boku:20180926203227j:plain

デフォルトのままでも、なんとなく使えたりします。

でも・・。

日本語をちゃんと扱うには、ちょっと気をつけないといけないポイントがあります。

何となく開発・テストしてるときには気づかないのですが、例えば、テストの最終段階とかで、ちょっとした問題(文字化けとかエラーとか)があって、調べてみると日本語処理の問題だったと気付いて大慌てする。

そんなことが、ままあります。

そうなると、そこから修正するのは結構面倒くさかったりします。

自分でもはまりましたから・・間違いないです(笑)。

なので、備忘をかねてまとめておきます。

なお、例では、データベースにMariaDB(10.3)を使っています。

 

気を付けるポイント

 

最初に箇条書きでポイントを書いておきます。

  1. MariaDBのキャラクタセットは「utf8mb4」にする。
  2. MariaDBの照合順序も「utf8mb4_xx」に変更する。
  3. PHPの文字列関数は「mb_」が頭についたものを使う。

以下にそれぞれを説明します。

 

MariaDBのキャラクタセットは「utf8mb4」にする

utf8では何故いけないのか?

それは、4バイト漢字が正しく処理されないからです。

www.softel.co.jp

だから、MariaDBMySQL)のキャラクタセットは、絶対「utf8mb4」にしておく必要があります。

my.iniとかのキャラクタセットを確認して、以下と違ってたら変更します。

[mysqld]
character-set-server=utf8mb4
[client]
default-character-set=utf8mb4

clientのdefault-character-setは、バージョンによっては「utf8mb4」が無指定でもデフォルトになっている場合もありますが、念のため、指定して損はないです。

show variables like '%char%';

 で確認して、以下のようになってたらOKです。

f:id:arakan_no_boku:20180922130051j:plain

character_set_sysytem はutf8のままでいいです。

もし、databaseとかがutf8か他の文字コードのままで残っていたら、以下のコマンドを使って変更しておきましょう。

データベース

ALTER DATABASE {DB名} CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

テーブル

alter table テーブル名 default character set utf8mb4;

 

MariaDBの照合順序も「utf8mb4_xx」に変更する 

 

上記の「COLLATE utf8mb4_general_ci;」のことです。

意外に忘れがちなんですが、照合順序(Collation)というのはとても重要です。

ざっくり、キャラクターセットが文字コードなら、照合順序はソート順・・ですかね。

だから、キャラクターセットがutf8mb4にするなら、照合順序もutf8mb4にしとかないとダメだよ・・というのは直観的にわかります。

照合順序には大きく3種類あります。

実際には、ユニコード照合アルゴリズム(UCA)の違いとかで、もう少し種類がありますが、そこまで意識することは、ほとんどの人は一生無いので割愛します。

  • utf8mb4_bin  : 英字の大文字小文字を含めて、すべて区別します。
  • utf8mb4_general_ci :英字の大文字小文字は区別しない。他は全て区別します。
  • utf8mb4_unicode_ci :大文字小文字/全角半角を区別しない。

デフォルトは、utf8mb4_general_ci です。

なので、一応、うえの例でもそうしてます。

でも。

実は、これが結構くせ者です。

実務上で、英字の大文字と小文字を区別しない場合って、そんなにありません。

暗黙のうちに、区別するつもりで開発が進んでて、テストとかで「ならび順がおかしい」とか「マッチしないはずのデータが表示されている」などの、ユーザからのクレームで気が付いて・・大慌てってことがあるからです。

ここは、よく考えて決めるべきです。

ちなみに、自分は常に「utf8mb4_bin」に変更してます。

あわせる場合は、うえの例の「utf8mb4_general_ci」の部分を置き換えて実行します。

変更できたかの確認は以下のSQLで行います。

SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'dbname';

ちなみに、余談ですが。

MariaDBを使っているなら、上記コマンドはHeidiSQLの「クエリ」ウインドウで実行するのが楽です。

正直、コマンドラインMySQLを使うより楽です。

特にDBにSSL接続しないといけない場合の面倒くささが全然違いますから。

 

PHPの文字列関数は「mb_」が頭についたものを使う

 

PHPには「strpos()」とか「strlen()」などの文字列関数があります。

でも、これは日本語のようなマルチバイト文字には対応してません。

だから、「mb_strpos()」とか「mb_strlen()」みたいなマルチバイト対応の文字列関数を代わりに使わないとダメです。

これを混在させていると、結構、泣きを見ることがでてきます。

だから、mb_*の文字列関数があるなら、全部そちらを使いましょう・・となります。

f:id:arakan_no_boku:20180922134306j:plain

今時、デフォルトのエンコーディングはUTF8になってますが、念のため(バージョンとかもあるので)確認して、そうでなかったら、先頭で「mb_internal_encoding("UTF-8");」を呼ばねばいけないとか・・、まあ、気をつけるポイントはありますね。 

えーと。

こんな感じかな。