はじめに
Laravelで日本語の比較処理をしようとしたところ、違う文字列であるにも関わらず同じものとして扱われてしまうことがありました。
その時の対処法を忘れないように記事にしたいと思います。
動作確認環境
- PHP 8.0
- Laravel 8.0
- MySQL 8.0
※下位環境でも動作する場合がございます
テーブル構造
問題点
$nana = Sample::where('name', 'バッグ')->get();
この処理。一見だと違う文字列であるため、一致する値は取得できないように思えますが、実はID:1の情報が返ってきてしまいます。
解決法1
$nana = Sample::where('name', 'LIKE BINARY', 'バッグ')->get();
あいまい一致を回避するためにはLaravelでは'LIKE BINARY'を付けることで完全一致に切り替えることができます。
解決法2
ただ、解決法1ではSelect文の時は回避できるのですが、該当カラムにユニークキーが貼られていた場合、Insertは依然として通りません。
該当カラムにユニークキーを使っている場合は、該当カラムの参照順序(文字コード)を変えてしまいましょう。
MySQLのバージョンにもよりますが8.0.2以降であれば、utf8mb4_ja_0900_as_cs_ksを使っておけば無難です。
※MySQL8系が使えない場合はutf8mb4_binが無難です(適時読み替えて下さい)
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// マイグレーションの書き方
Schema::create('samples', function (Blueprint $table) {
$table->id();
$table->string('name')->unique()->collation('utf8mb4_ja_0900_as_cs_ks');
$table->timestamps();
});
}
解決法3
文字コードで混乱しなくないという場合は、Laravelのconfig/database.phpの設定を書き換えてしまうのが簡単です。
MySQL 8.0.2以降を使用する場合は下記の設定しておけば問題ないかと思います。
マイグレーションした際の初期値がutf8mb4_ja_0900_as_cs_ksになります(個別設定は不要)。
※なお、MySQL8系が使えない場合はutf8mb4_binが無難です(適時読み替えて下さい)
'mysql' => [
...
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_ja_0900_as_cs_ks',
...
],
参考記事