プログラミングノート

プログラミングの備忘録です

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