5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelで違う文字(濁点/半濁点/平仮名/片仮名)が同じ文字として使われてしまう問題の対処法

Last updated at Posted at 2021-06-21

はじめに

Laravelで日本語の比較処理をしようとしたところ、違う文字列であるにも関わらず同じものとして扱われてしまうことがありました。
その時の対処法を忘れないように記事にしたいと思います。

動作確認環境

  • PHP 8.0
  • Laravel 8.0
  • MySQL 8.0

※下位環境でも動作する場合がございます

テーブル構造

image.png
image.png

問題点

$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',
    ...
],

参考記事

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?