"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

PHP+MariaDBで日本語を正しく使うための3つのポイントを整理する(備忘)

f:id:arakan_no_boku:20180926203227j:plain

目次

PHPMariaDBで日本語を正しく使うための3つのポイント

PHPMariaDBで日本語を使うときに気をつけないといけないのは以下の3つです。

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

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

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

 

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

utf8ではありません。

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)というのはとても重要です。

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

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

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

デフォルトは、utf8mb4_general_ci です。

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

でも。

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

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

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

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

別記事に、これだけをとりあげて書いているものがあるので、よければどうぞ。

arakan-pgm-ai.hatenablog.com

あわせる場合は、うえの例の「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");」を呼ばねばいけないとか・・、まあ、気をつけるポイントはありますね。 

えーと。

こんな感じかな。