PHP の PDO の使い方|プリペアドステートメントで SQL インジェクションを防ぐ
PHP でデータベースを使うときの基本。PDO のつなぎ方、プリペアドステートメントで SQL インジェクションを防ぐ方法、間違えやすい所をまとめた。
SQL インジェクションは、入力された文字で SQL を書き換えられ、データを抜き取られたり消されたりする弱点。PHP では PDO のプリペアドステートメントを使えば防げる。
この記事の要点
- 入力された値を、SQL の文字列に直接つなげない
- PDO の
prepare()と、値の受け渡し(execute()の引数)を使う PDO::ATTR_EMULATE_PREPARESを false にすると、より安全- 古い
mysql_*関数は PHP 7.0 で削除されている
危ない書き方と安全な書き方
| 書き方 | |
|---|---|
| 危ない | SQL の文字列に $_GET['id'] などを直接つなげる |
| 安全 | prepare('SELECT * FROM users WHERE id = ?') のあと execute([$id]) |
| 安全 | 名前で渡す:WHERE email = :email と execute(['email' => $email]) |
つなぐときの設定
- エラーのときに例外を投げる:
PDO::ATTR_ERRMODEをPDO::ERRMODE_EXCEPTION(PHP 8.0 から既定) - 本物のプリペアドステートメントを使う:
PDO::ATTR_EMULATE_PREPARESを false - 文字コードは接続の文字列で
charset=utf8mb4を指定する
間違えやすい所
- 並べ替えの列名(ORDER BY)やテーブル名は、値として渡せない。許す名前の一覧から選ぶ
IN (...)は、値の数だけ?を並べる- 検索の
LIKEも、値として渡す(%は値の側に付ける)
古いプログラムの移行と一緒に
mysql_* 関数を使った古いプログラムは、PHP 7.0 以降で動かない。PHP を上げるときに、PDO へ書き換えるのがちょうどよい。
よくある質問
エスケープの関数を使えば、プリペアドステートメントは要りませんか?
プリペアドステートメントを使ってください。
エスケープは使い方を間違えやすく、漏れが出やすいです。
mysqli でもプリペアドステートメントは使えますか?
使えます。
考え方は PDO と同じで、値を SQL の文字列につなげずに渡します。
参考にした情報
この記事の情報
2026年10月22日時点の公開情報にもとづく。画面や手順は変わることがあるので、最新は各社の公式のマニュアルを確認すること。
URL を入れるだけで、PHP2Shell の危険度と今やることが分かる。移行の相談もできる。
無料で診断する


