PDOでprepareの使い方【PHP】

PDOで使用できるprepareの使い方をまとめました。

PDOでSQL文を実行するにあたっては、効率面でもセキュリティ面でも、とても重要な機能なので、詳しくない方は是非最後まで目を通してください。

prepareとは

prepareとは、PDOで使用できるメソッドの1つで、SQL文をセットして実行準備を行います。

//SQLクエリを生成
$sql = "SELECT *
        FROM users
        WHERE id = :id
        AND password = :password";

//prepareによるクエリの実行準備
$sth = $pdo -> prepare($sql);

//クエリの設定
$sth -> bindValue(':id', 999);
$sth -> bindValue(':password', 'hogehoge');

//クエリの実行
$sth -> execute();

//結果を配列で取得
$data = $sth -> fetch(PDO::FETCH_ASSOC);

//空の配列でなければログイン成功
if($data){
    echo 'ログイン成功!';
}

prepareの実行の流れは次の通りです。

prepare解説

要するに、「SQL文だけ作っておいて、値(変数など)を後から当てはめる」という形式です。

ちなみに値の代入を行わない(bindValueを使用しない)場合でも、prepareは使用できます。

//SQLクエリを生成
$sql = "SELECT *
        FROM users
        WHERE id = 999
        AND password = 'hogehoge'";
        
//prepareによるクエリの実行準備
$sth = $pdo -> prepare($sql);

//クエリの実行
$sth -> execute();

prepareとqueryの違い

PDOでSQLを実行するにあたって、queryではなくprepareを使用しなくてはいけないシーンは沢山あります。

prepareとqueryの違いについてまとめました。

SQLインジェクションを防げる

不正な値を入力してSQL文を改ざんさせられる「SQLインジェクション」という攻撃があります。

参考 PHPでSQLインジェクション攻撃の対策方法【PDO】

queryの場合

例えば、以下のようにユーザーから送信された値を何の検証もせずSQL文に組み込み、queryで実行すると、処理を改ざんさせられる恐れがあります。

$sql = "SELECT * 
        FROM users 
        WHERE id = '".$_POST['user_id']."' 
        AND password = '".$_POST['user_pass']."'";
$sth = $pdo -> query($sql);

例えば、このような文字列連結でクエリを実行してしまった場合…。

$_POST[‘user_id’]に「’ OR 1=1;–」という値を送信されてしまうと、idとパスワードの一致を問わずデータが取得できてしまうため、不正ログインに繋がる恐れがあります。

不正ログインに限らず、DELETE文でデータを破壊される恐れもあり、本当に好き放題荒らされる可能性を孕んでいます。

prepareの場合

では、prepareで同じことをした場合はどうなるか見てみましょう。

$sql = "SELECT * 
        FROM users 
        WHERE id = :id
        AND password = :password";
//prepareによるクエリの実行準備
$sth = $pdo -> prepare($sql);
//クエリの設定
$sth -> bindValue(':id', $_POST['user_id']);
$sth -> bindValue(':password', $_POST['user_pass']);
//クエリの実行
$sth -> execute();

prepareは、値が入る前にSQL文の実行準備を行います。

なので、例えば:idにあたる部分にクエリを改ざんさせられるような値を送信されても、「id」との比較でしか使用されません。

準備の段階から「:」のコロン付きパラメータがどう使用されるかを確定させることが出来るため、安全な仕組みを作ることが出来ます。

同じSQL文を繰り返し使用できる

同じSQL文で値(変数)のみを切り替える、という処理は、prepareを使用するとより使いまわしが利きます。

例として、このようなテーブルを使用します。

table名:yasai_item
id name price
1 にんじん 50
2 トマト 100
3 きゅうり 80
サンプルコード
$aryId = [1, 3];
$sql = "SELECT name FROM yasai_item WHERE id = :id";
//prepareによるクエリの実行準備
$sth = $pdo -> prepare($sql);

foreach($aryId as $id){
    $sth -> bindValue(':id', $id);
    $sth -> execute();
    $name = $sth -> fetch(PDO::FETCH_COLUMN);
    echo $id.':'.$name."<br>";
}
1:にんじん
3:きゅうり

同じSQL文で、取得したいidに応じた野菜の名前を取得する処理です。

取得したいidを配列に入れて、foreachで繰り返し、それぞれのidをexecuteで実行しています。

参考 PHPのforeachを徹底解説【サンプルコード有】

このように、同じSQL文で条件となる値だけ変えたい、といった場合にも、prepareは効率的に利用できます。


PDOを活用するにあたって、prepareのメソッドと切っても切り離せない存在です。

何故prepareを使用しなくてはいけないのかを理解した上で、PDOを利用していきましょう。

各SQL文毎のprepareの利用方法は下記の記事をご確認ください。

以上、PDOでprepareの使い方、でした。

PHP