LaravelのEloquentでLike検索する

LaravelのEloquentでLike検索するとき、検索キーワードをエスケープしないと、予期しない結果が返ることがあります。

// エスケープしないコードの例
$products = Product::where('name', 'like', '%'.$name.'%')->get();

productsテーブルには、「オレンジ100%」と「オレンジ100個分」が登録されています。

>>> Product::all();
=> Illuminate\Database\Eloquent\Collection {#4148
     all: [
       App\Product {#3901
         id: 1,
         name: "オレンジ100%",
       },
       App\Product {#3533
         id: 2,
         name: "オレンジ100個分",
       },
     ],
   }

キーワード「100%」で検索します。

>>> $name = '100%';
=> "100%"

キーワードをエスケープせずに検索すると、キーワードを含まないレコードもヒットします。

>>> Product::where('name', 'like', '%'.$name.'%')->get();
=> Illuminate\Database\Eloquent\Collection {#3218
     all: [
       App\Product {#4151
         id: 1,
         name: "オレンジ100%",
       },
       App\Product {#4006
         id: 2,
         name: "オレンジ100個分",
       },
     ],
   }

キーワードをエスケープする関数を作成します。

>>> function escape_like(string $value, string $char = '\\'): string
... {
...     return str_replace(
...         [$char, '%', '_'],
...         [$char.$char, $char.'%', $char.'_'],
...         $value
...     );
... }

キーワードをエスケープして検索します。

>>> Product::where('name', 'like', '%'.escape_like($name).'%')->get();
=> Illuminate\Database\Eloquent\Collection {#4165
     all: [
       App\Product {#4170
         id: 1,
         name: "オレンジ100%",
       },
     ],
   }

正しい結果が得られました。

参考:Laravel: Escape “LIKE” clause?

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください