Help us understand the problem. What is going on with this article?

pdoでLIKE検索する際の注意点

More than 3 years have passed since last update.

前提

あくまでもMysqlだけでの話を前提としてお話します。
先日自分が書いたコードで指摘を受けたため、備忘録として残しておきます。

実際あったコード

ユーザが本のタイトルをLIKE検索したく、下記のようにPDOで実装を行っていました。

$sql = 'select * from books where title like ?';
$stmt = $dbh->prepare($sql);
$stmt->execute(array(sprintf('%%%s%%', $title)));

$result = $stmt->fetchAll();

ここで、$title には、ユーザが入力した検索したい本の名前が入っているものとします。
受けた指摘としては、ユーザが[%]や[_]という文字列を検索したい場合に正しく動作するか?というものでした。

Mysqlでは、LIKE検索に使われる特殊文字列下記のようなものがあります。

% -> 任意の0文字以上の文字列
_ -> 任意の1文字

これで問題が起きる場合

例えばユーザが「100%」という文字列を検索したとします。
ユーザとしては、「株式投資で100%成功する方法」とか「告白が100%成功する方法」とかを期待してると思います。

が、実際に実行されるSQLは

select * from books title like '%100%%';

となり、結果は下記のようになります。

  • 1. 株式投資で100%成功する方法
  • 2. 告白が100%成功する方法
  • 3. 最後から100番目の恋
  • 4. 100回目のプロポーズ

おや、最初の2つは期待どおりですが、最後の2つは期待ハズレのものが返って来てます。

これは、先ほどの、MysqlがLIKE検索で%が任意の0文字以上の文字列という意味を持っているため、
ユーザが調べようとした100%%は本来の文字列としての%ではなくて、任意の0文字以上で判別されてしまって、
100という文字列を含むタイトルが検索されてしまったのです

じゃあどうするか

↑で説明したとおり、MysqlのLIKE検索において、%_は特殊な意味を持つため、この2つをエスケープして上げる必要があります。
具体的には下記のように。

$sql = 'select * from books where title like ?';
$stmt = $dbh->prepare($sql);
$stmt->execute(array(sprintf('%%%s%%', addcslashes($title, '\_%')));

$result = $stmt->fetchAll();

PHPの場合はこれで%_がエスケープされるため、正しく検索が行えるようになります。

とても初歩的な事ですが、ハマってしまった自分が恥ずかしい。。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした