初めに
- PHP/Mysqlを使用して1年ほど
- Symfony:ORM(doctorin)やLaravelを半年ずつほど
概要
PHPでDBを操作する際によくSQL文を記載して簡単に「query」する方法と
$member = $db->query('SELECT * FROM user');
条件値を後から動的に「prepare/bindValue/execute」で設定する方法がありますが
$stmt = $pdo->prepare("SELECT * FROM user WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::hogehoge);
$stmt->execute();
各関数がどのような処理をしているのか理解しないで使用していました。。
①ではなぜ使い分ける必要があるのかにフォーカスを当てて確認したいと思います
1. 2通りのクエリ方法について
静的なSQL文を使用する機会や、SQL文を動的変えたい場合があると思います。
各用途ではどのようになっているのか、簡単に調べてみました。
SQL文が静的→「query」を使用
SQL文が動的→「prepare/bindValue/execute」を使用
上記から、「動的」=SQL文に「変動値」が入るかで使い分けているイメージになります。
2. 使い分ける理由について
PHPの記述上、「query」でも変数を使用した動的なSQLが書けます。
$sql = "SELECT * FROM user WHERE name='$name'";
$pdo->query($sql);
上記SQL文でプログラムは動きますが、推奨しない理由がありました。
SQL文の中に変動値が入る場合、PHPの変数を直接連結してしまうと「SQLインジェクション攻撃」により悪意のあるSQLが実行されてしまう可能性がある。参照リンク
要するに、情報流出のリスクといった感じで解釈しています。
上記から「プレースホルダ」という仕組みを使い「SQLインジェクション攻撃」を防ぐクエリ方法が「prepare/bindValue/execute」になります。
※プレースホルダにも静的/動的がありますが説明の関係上省略しています。
ざっくりとした仕組みのイメージ
「PDO」
↳「プレースホルダ」
↳「prepare/bindValue/execute」
「prepare/bindValue/execute」を使用した簡単な記述例
$stmt = $pdo->prepare("SELECT * FROM user WHERE id=:id");
$stmt->bindValue(':id', $id, PDO::hogehoge);
$stmt->execute();
まとめ
- 「query」でも動的クエリはできるけど「prepare/bindValue/execute」を使った方が良い。
- 実作業でも「変動値」があるSQL文がほとんどなので覚えた方が書きやすい。
- 書き方でどのようなリスクがあるのかは保守の観点やPGとして必要な感覚だと思うのでアンテナを張っていきたいです。