PDO::prepare
文を実行する準備を行い、文オブジェクトを返す
説明
public PDOStatementfalse PDO::prepare(string $query
, array $options
= [])
PDOStatement::execute をコールする際には、
文に渡すパラメータにはそれぞれ固有のパラメータマークを設定する必要があります。
エミュレーションモードが有効になっていない限り、
ひとつのプリペアドステートメントの中で、同じ名前のパラメータマークを
複数使用することはできません。
注意:
パラメータマーカーが表せるのは、データリテラルだけです。
リテラルの一部やキーワード、識別子、その他のクエリのパーツをパラメータにバインドすることはできません。
たとえば、SQL 文の IN() 句などで、
ひとつのパラメータに複数の値を割り当てることはできません。
異なるパラメータを用いて複数回実行されるような文に対し
PDO::prepare と
PDOStatement::execute をコールすることで、
ドライバがクライアントまたはサーバー側にクエリプランやメタ情報を
キャッシュさせるよう調整するため、
アプリケーションのパフォーマンスを最適化します。また、
パラメータに手動でクオートする必要がなくなるので
SQL インジェクション攻撃から保護する助けになります。
PDO は元々この機能をサポートしていないドライバに対して
プリペアドステートメントとバインドパラメータをエミュレートします。
このため、ある形式をサポートしているがその他の形式をサポートしていない
ドライバの場合、名前もしくは疑問符形式のパラメータを他の適当な値に
書き換えることも可能です。
注意:
エミュレートされたプリペアドステートメントと、
名前パラメータやクエスチョンマークを書き換えるパーサは、[シングル|ダブル]クォート
に対して標準とは異なるエスケープをサポートしています。
これによって、バックスラッシュのすぐ後にクォートで終了するクエリは
そのままの形では認識されず、間違ったパラメータとして認識され、
実行されたときにプリペアドステートメントが失敗してしまいます。
回避策は、プリペアドステートメントのエミュレートをこの手のSQLクエリでは使わないようにしつつ、
ドライバによってサポートされているパラメータの書き換えを避けることです。
PHP 7.4.0 以降では、クエスチョンマークを2回続けることで、
クエスチョンマークそのものをエスケープすることができます。
これは、??
という文字列が、
クエリをデータベースに送信する時に ?
に変換されるということです。
パラメータ
-
query
-
これは対象のデータベースサーバーに対して有効な SQL
文のテンプレートでなければなりません。
-
options
-
この配列は、このメソッドによって返される PDOStatement
オブジェクトに対して 1
もしくはそれ以上の key=>value の組を含みます。
通常、スクロール可能なカーソルを要求するために
PDO::ATTR_CURSOR
に
PDO::CURSOR_SCROLL
を設定する場合に使用することになるでしょう。
いくつかのドライバには、準備する際に利用可能なドライバ固有の
オプションがあります。
戻り値
もしデータベースサーバーが正常に文を準備する場合、
PDO::prepare は
PDOStatement オブジェクトを返します。
もしデータベースサーバーが文を準備できなかった場合、
PDO::prepare は false
を返すか
PDOException を発行します
(エラー処理 の方法に依存します)。
注意:
プリペアドステートメントをエミュレートする際にデータベースサーバーとの通信は行いません。
したがって PDO::prepare はステートメントのチェックを行いません。
エラー / 例外
PDO::ATTR_ERRMODE
が PDO::ERRMODE_WARNING
に設定されていた場合、E_WARNING
レベルのエラーが発生します。
PDO::ATTR_ERRMODE
が PDO::ERRMODE_EXCEPTION
に設定されていた場合、PDOException がスローされます。
例
例1 名前付きパラメータを用いて SQL ステートメントのテンプレートを準備する
<?php
/* 値の配列を渡してプリペアドステートメントを実行する */
$sql = 'SELECT name, colour, calories
FROM fruit
WHERE calories < :calories AND colour = :colour';
$sth = $dbh->prepare($sql, [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);
$sth->execute(['calories' => 150, 'colour' => 'red']);
$red = $sth->fetchAll();
/* 配列のキーの前にも、コロン ":" を付けることができます(オプション) */
$sth->execute([':calories' => 175, ':colour' => 'yellow']);
$yellow = $sth->fetchAll();
?>
例2 疑問符パラメータを用いて SQL ステートメントのテンプレートを準備する
<?php
/* 値の配列を渡してプリペアドステートメントを実行する */
$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->execute([150, 'red']);
$red = $sth->fetchAll();
$sth->execute([175, 'yellow']);
$yellow = $sth->fetchAll();
?>
例3 クエスチョンマークをエスケープした、SQLステートメントのテンプレート
<?php
/* 注意: 以下は PostgreSQL の場合にのみ有効です */
$sth = $dbh->prepare('SELECT * FROM issues WHERE tag::jsonb ?? ?');
$sth->execute(['feature']);
$featureIssues = $sth->fetchAll();
$sth->execute(['performance']);
$performanceIssues = $sth->fetchAll();
?>
参考
- PDO::exec
- PDO::query
- PDOStatement::execute