PHP Data Object (PDO)でプリペアステートメントを使う 第2回
PHP Data Object (PDO)を用いて、プリペアステートメントを使います。
プリペアステートメントを使ってSQLを作成しデータベース操作を行うと、セキュリティの向上や処理の効率化が期待できます。
1.プリペアステートメントを使うメリット
1-1.セキュリティの向上
Webページで不正な入力を行い想定外のSQLを生成させて、データベースを不正に操作する攻撃(SQLインジェクション)を防ぐ効果があります。
1-2.処理の効率化
SQLを実行する時、SQLの解析、コンパイル、最適化といった準備が行われます。プリペアステートメントを使ってSQLを作成すると、1回目はこれらの準備を行いますが、2回目以降はこれらの準備を省きます。(SQL文に埋め込む変数を指定することで、SQL文の値を変えることができます。)
2.プリペアステートメントの使用
PDOのプリペアステートメントを使用します。PDOの導入とPDOインスタンスの作成については、PHP Data Object(PDO)拡張モジュールの導入とPDOインスタンスの作成 第1回 - プログラミングノート をご覧ください。
2-1.PDOインスタンスの作成
データベースのDNS、ユーザー、パスワードをPDOクラスのコンストラクタに渡して、PDOインスタンスを作成します。
データベースのDNS、ユーザー、パスワードはご利用環境に合わせてください。
コンストラクタの詳細は PHP: PDO::__construct - Manual をご覧ください。
$dsn = 'mysql:dbname=testdb;host=testhost';
$user = 'testuser';
$password = 'testpass';
$dbh = new PDO($dsn, $user, $password);
2-2.SQL文の指定
prepareメソッドを使いSQL文を指定します。SQL文は変数を埋め込む箇所にプレースホルダを挿入し作成します。
プレースホルダとは、SQL文の変数を埋め込む箇所を示すマークです。後から、プレースホルダに変数を関連づける必要があります。
プレースホルダには、名前つきプレースホルダと「?」プレースホルダの2種類があります。
prepareメソッドの詳細は PHP: PDO::prepare - Manua をご覧ください。
名前つきプレースホルダ
「VALUES」の後の「:no」と「:name」がプレースホルダとなります。
$stmt = $dbh->prepare("INSERT INTO TEST (no, name) VALUES (:no, :name)");
「?」プレースホルダ
「VALUES」の後の「?」2つがプレースホルダとなります。
$stmt = $dbh->prepare("INSERT INTO TEST (no, name) VALUES (?, ?)");
2-3.プレースホルダと変数を関連付ける
どのプレースホルダにどの変数の値を入れるのか指定するため、bindParamメソッドを使って、プレースホルダと変数を関連付けます。
bindParamメソッドの詳細は PHP: PDOStatement::bindParam - Manual をご覧ください。
名前つきプレースホルダを使用した場合
bindParamメソッドの引数は、1つ目が「'」で囲んだプレースホルダの名前(例:':no')で、2つ目が変数となります。
$stmt->bindParam(':no', $no);
$stmt->bindParam(':name', $name);
「?」プレースホルダを使用した場合
bindParamメソッドの引数は、1つ目がプレースホルダの順番で、2つ目が変数となります。
1つ目のプレースホルダの順番と2つ目の変数がずれないように注意します。
$stmt->bindParam(1, $no);
$stmt->bindParam(2, $name);
2-4.SQLの実行
executeメソッドを使ってSQLを実行します。
executeメソッドの詳細は PHP: PDOStatement::execute - Manual をご覧ください。
$stmt->execute();
また、executeメソッドの引数でプレースホルダと変数の関連付けを行い、SQLを実行することもできます。
executeメソッドの引数は配列である必要があります。配列の要素の1つ目から順にプレースホルダに関連付けられます。
$stmt = $dbh->prepare("SELECT * FROM TEST where name = ?");
$stmt->execute(array($name));
2-5.抽出結果を取得
クエリで抽出した結果を1行ずつ取得するにはfetchメソッドを使います。
fetchメソッドの詳細は PHP: PDOStatement::fetch - Manual をご覧ください。
while ($row = $stmt->fetch()) {
print_r($row);
}
補足
WHERE句にLIKEと%を含むSQL文を作成する場合、SQL文のWHERE句は「WHERE xxxxx LIKE ?」となります。
プレースホルダには変数を関連付けないといけません。そのため、変数と「%」を連結した値を変数に代入し、その後、代入した変数をプレースホルダと関連付けます。
$stmt = $dbh->prepare("SELECT * FROM TEST where name LIKE ?");
$keyword_name = "%".$name."%";
$stmt->bindParam(1, $keyword_name);
$stmt->execute();
記事一覧
第1回 PHP Data Object(PDO)拡張モジュールの導入とPDOインスタンスの作成
第2回 PHP Data Object (PDO)でプリペアステートメントを使う
第3回 PHP Data Object(PDO)でトランザクションを利用する
参考
PHP: プリペアドステートメントおよびストアドプロシージャ - Manual