【PHP】文字列検索のSQL文・LIKEでプレースホルダを使用する

検索サイトを作りたいなと思い、ちょいちょいPHPやSQLについて勉強したり、コードを書いたりしているのですが、PHPでプレースホルダを使用するのに少し手間どったのでその備忘録です。

データベースとSQLインジェクション

データベース(SQL)に関する脅威といえば、みなさまご存じSQLインジェクション。
不正な入力を行うことでデータベースを操作したり、データを不正に取得したりする攻撃です。

主な対策としては、
・SQL文の組み立てをプレースホルダで行う
・エスケープ処理を行う
などがあります。

具体的な内容とか対策とかについては、以下のIPAの資料などを読んでください。

安全なウェブサイトの作り方 - 1.1 SQLインジェクション | 情報セキュリティ | IPA 独立行政法人 情報処理推進機構
情報処理推進機構(IPA)の「安全なウェブサイトの作り方 - 1.1 SQLインジェクション」に関する情報です。

安全なSQLの呼び出し方(PDF)

検索サイトとアウトなコード

実装の調査用に、こんな感じの簡易データベース表示サイトを作りました。
(データについては英語版WikipediaのNPBの記事より。実行環境はMAMP。)

球団名を部分一致で検索できる入力フォームを付けています。
以下は球団名に「ス」を含む球団を検索した結果。

文字列の部分検索にはLIKEを使用します。SQL文は以下。

今回の検索文字列を受け取って、SQLの実行と結果を取得するPHPのコードが以下です。
HTMLで入力された値を確認も何もしていないうえに、そのままSQL文に入れています。ちなみにクライアント(HTML、JavaScriptは使ってない)側でも入力チェックなどは特に何もしてません。SQLインジェクションしてくれと言わんばかりのスリーアウトなコードです。野球だけに。

これにプレースホルダを適用してセーフなコードにします。

PHPでプレースホルダを使用する

『PHP プレースホルダ』とかで検索すると、prepareメソッドを使用することが分かりました。
いろいろ出てきたコードを基に、上記のコードを修正してみました。

が、上手くいかないというか画面に何も表示されず真っ白になる。

更にいろいろ調べたところ、LIKEの場合のprepareの書き方が間違っていたらしい。

他にもたくさん間違っていたところがありました(bindValueを使用したものとか、元々のコードと混乱したのが原因)。
正しいコードはこちら。

ちゃんとプレースホルダ未使用の時と同じような表示結果が得られました!

なおbindValueを使う場合にはexecuteの引数が不要。

コード全体

一応PHPとHTMLのコード全体も載せておきます。PDOのテーブル名、ID、PASSWORDには実際の値を入れてください。
調査用の簡易的なものなので、いろいろ雑なのはスルーしてください。

データベースはこんな感じでした。

セリーグ球団の設立年というか設立順は知ってたけど、パリーグの方は全然知らなかったので勉強になりました。あとみんな11月~2月の間なんだなーと思ったけど単にオフシーズンってだけですね。
今年は結構荒れそうなので楽しみ半分不安半分だ……。

参考

以下のサイトを参考に解決することができました。ありがとうございます。

【php】 PDOのプリペアドステートメントでLIKE検索 at softelメモ
問題 PDOのプリペアドステートメントでLIKE検索したいです。 書き方は? 答え 以下でよい。 $db = new PDO('mysql:host=localhost;dbname=xxxx', 'xxxx', 'xx ...
PDOのプリペアドステートメントでLIKE句とワイルドカードを使う方法 | プログラマーになった 「中卒」 男のブログ
MySQL の基本操作 (3)
PHPから MySQL に接続する方法やプリペアドステートメント、PDO を使った接続等に関する参考資料・解説等。PHPから MySQL に接続, ユーザーの追加, 文字エンコードの指定とセキュリティ, MySQL への接続 / mysql...

コメント

タイトルとURLをコピーしました