PHP-DB - 14. 名前つきプレースホルダ

引き続きプリペアドステートメントについて学習します。ここでは名前つきプレースホルダについて取り上げます。これまでに学習してきたとおり、プリペアドステートメントを使う場合、SQLに ? プレースホルダを使用できます。

insert into categories (id, title) values (?, ?)

またPHPにおいて、プレースホルダにデータをバインドするには PDOStatement クラスの bindValue メソッドを呼び出します。

    $ps->bindValue(1, $id, PDO::PARAM_INT);
    $ps->bindValue(2, $title, PDO::PARAM_STR);

このときプレースホルダの数が多くなると、先頭から何番目のプレースホルダにデータをバインドするのか数えてから、引数を正しく指定する必要がありました。次に学習する名前つきプレースホルダを使用すると次のようにSQLを定義できます。

insert into categories (id, title) values (:id, :title)

さきほどの ? 記号の部分が :id:ttile といった表記に置き換わっています。このような記述を名前つきプレースホルダと呼びます。

またPHPにおいて、名前つきプレースホルダにデータをバインドするには以下のように PDOStatement クラスの bindValue メソッドを呼び出します。

  $ps->bindValue(":id", $id, PDO::PARAM_INT);
  $ps->bindValue(":title", $title, PDO::PARAM_STR);

bindValue メソッドの第1引数が整数値( 12 )ではなく ":id"":title" を指定している点を確認してください。このように名前つきプレースホルダを使えばプレースホルダとデータのバインドを管理しやすくなります。それでは次のプログラム( pdo12.php )を作成してみましょう。

<?php
try {
    $dsn = "sqlite:eldb.sqlite3";
    $username = null;
    $passwd = null;
    $pdo = new PDO($dsn, $username, $passwd);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $sql = "insert into categories (id, title) values (:id, :title)";
    $ps = $pdo->prepare($sql);

    $id = 5;
    $title = "Biz";
    $ps->bindValue(":id", $id, PDO::PARAM_INT);
    $ps->bindValue(":title", $title, PDO::PARAM_STR);

    $ps->execute();
    $count = $ps->rowCount();
    echo "Count: $count" . PHP_EOL;  
} catch (PDOException $e) {
    echo $e->getMessage() . PHP_EOL;
}

このプログラムではSQLに名前つきプレースホルダを使用しています。

    $sql = "insert into categories (id, title) values (:id, :title)";
    $ps = $pdo->prepare($sql);

SQLのプレースホルダが通常の ? ではなく :id:title となっている点に注意してください。

次に名前つきプレースホルダにデータをバインドします。

    $id = 5;
    $title = "Biz";
    $ps->bindValue(":id", $id, PDO::PARAM_INT);
    $ps->bindValue(":title", $title, PDO::PARAM_STR);

残りの処理はこれまでと変更ありません。それではコマンドラインからプログラムを実行してみましょう。

$ php pdo12.php
Count: 1

実行結果からSQLの更新件数(登録件数)が1件であることを確認できます。

まとめ

  • PHPのプリペアドステートメントは名前つきプレースホルダをサポートしている
  • ? を使わずに :id のような名前でプレースホルダを定義できる
  • bindValue メソッドにおいては番号ではなく名前でデータをセットする