teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

1

追記

2019/08/17 22:31

投稿

退会済みユーザー
answer CHANGED
@@ -1,3 +1,31 @@
1
1
  [PHP で MySQL 接続時に必要な知識(最小限版)](https://qiita.com/te2ji/items/56c194b6cb9898d10f7f)
2
2
 
3
- LIKE はチョットめんどいですよ
3
+ LIKE はチョットめんどいですよ
4
+
5
+ # **以下、追記**
6
+ まだクローズされていないので追記しておきます。
7
+
8
+ > selectのWHEREで変数を使いたい
9
+
10
+ 質問は「SELECT の WHERE の[リテラル](https://dev.mysql.com/doc/refman/5.6/ja/literals.html)を変数として使いたい」と読み替えることができます。
11
+
12
+ リテラルを変数で表現するには、プリペアドステートメントを使用し、クエリの構文とデータを分離し、構文を改変できないようにした上で、データをバインドする方法が[推奨](https://www.ipa.go.jp/files/000017316.pdf)されてます。
13
+
14
+ 質問では、せっかく prepare() を使用しているにも関わらず、適切なプリペアードステートメントが記述でされていません。変数を SQL 文に埋め込んでいるため、構文の改変を許してしまっています。
15
+
16
+ 正しい記述方法に関しては、[PHP で MySQL 接続時に必要な知識(最小限版)](https://qiita.com/te2ji/items/56c194b6cb9898d10f7f)を参照してください。
17
+
18
+ (**余談**:プリペアードステートメントで記述したクエリが DB でどの様にあつかわれるかは、[「13.5 準備済みステートメントのための SQL 構文 - dev.mysql.com」](https://dev.mysql.com/doc/refman/5.6/ja/sql-syntax-prepared-statements.html)の1番目のサンプルを見ておくと、イメージしやすいと思います。)
19
+
20
+ また、LIKE に関しても注意が必要です。
21
+ プリペアードステートメントを使用したデータバインドでは、エスケープやクオートは自動で判断されますが、ワイルドカード文字はその対象ではないため、自前でエスケープを記述する必要があります。
22
+ ワイルドカード文字はデータベースによって違いがあるため、データベースのマニュアルで必要な文字を確認しエスケープしてください。
23
+
24
+ 本件が MySQL であれば、後方のみで使用しているので
25
+ `bindValue(1, addcslashes($hani, '\_%') . '%', PDO::PARAM_STR);`
26
+ のような記述になります。
27
+
28
+ エスケープが正しく行われていない場合、例えば $hani に「%01」のような値が突っ込まれると「%01%」をバインドしてしまい、意図した内容ではない検索が行われます。
29
+ DB 処理では、製作者の意図しない挙動を制限する必要があるのでワイルドカード文字に対してのエスケープは必須です。
30
+
31
+ 参考記事で紹介している範囲は php でデータベース接続を扱うため必要なの最小限の知識なので、もっと詳しく説明している「[PHPでデータベースに接続するときのまとめ](https://qiita.com/mpyw/items/b00b72c5c95aac573b71)」も併せて読むと良いです。