PDO::prepare

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PHP 8,PECL pdo >= 0.1.0)

PDO::prepare 文を実行する準備を行い、文オブジェクトを返す

説明

public PDO::prepare(string $query, array $options = []): PDOStatement|false

PDOStatement::execute() メソッドによって実行される SQL ステートメントを準備します。 ステートメントのテンプレートは、文が実行されるときに実際の値に置き換えられる 0 個もしくはそれ以上の名前 (:name) もしくは疑問符 (?) パラメータマークを含むことができます。 名前と疑問符パラメータを同一の ステートメントのテンプレート中で使用することはできません。 どちらか一方か、他のパラメータ形式を使用してください。 ユーザーの入力をバインドする際にはこれらのパラメータを使います。 ユーザーの入力を直接クエリに含めてはいけません。

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_CURSORPDO::CURSOR_SCROLL を設定する場合に使用することになるでしょう。 いくつかのドライバには、準備する際に利用可能なドライバ固有の オプションがあります。

戻り値

もしデータベースサーバーが正常に文を準備する場合、 PDO::prepare()PDOStatement オブジェクトを返します。 もしデータベースサーバーが文を準備できなかった場合、 PDO::prepare()false を返すか PDOException を発行します (エラー処理 の方法に依存します)。

注意:

プリペアドステートメントをエミュレートする際にデータベースサーバーとの通信は行いません。 したがって PDO::prepare() はステートメントのチェックを行いません。

例1 名前付きパラメータを用いて SQL ステートメントのテンプレートを準備する

<?php
/* 値の配列を渡してプリペアドステートメントを実行する */
$sql 'SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour'
;
$sth $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array('calories' => 150'colour' => 'red'));
$red $sth->fetchAll();
/* 配列のキーの前にも、コロン ":" を付けることができます(オプション) */
$sth->execute(array(':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(array(150'red'));
$red $sth->fetchAll();
$sth->execute(array(175'yellow'));
$yellow $sth->fetchAll();
?>

例3 SQL statement template with question mark escaped

<?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() - SQL ステートメントを実行し、作用した行数を返す
  • PDO::query() - プレースホルダを指定せずに、SQL ステートメントを準備して実行する
  • PDOStatement::execute() - プリペアドステートメントを実行する

関連キーワード:  パラメータ, PDO, 実行, 準備, オブジェクト, ステートメント, プリペアドステートメント, prepare, PDOStatement,