
【 PHP学習 #29 】 データベース編⑤ 「PDO プリペアードステートメント/プレースホルダ」 FIREへの旅路 ♯483
前回にPDOを使って、PHPとデータベースを接続しました。
今回は、データベースの中のデータを、表示させる処理を行います。
【 表示用のファイルを作成 】
前回のPDO用のファイルと同じ階層に新たなファイルを作成します。
mainte / index.php です。
■ index.php
<?php
//データベースと接続 解説①
require 'db_connection.php';
//ユーザー入力なしの場合 解説②
$sql = 'select * from contacts where id = 2'; //sql文
$stmt = $pdo->query($sql); //sql実行
$result = $stmt->fetchAll();
echo '<pre>';
var_dump($result);
echo '</pre>';

<解説①>
//データベースと接続 解説①
require 'db_connection.php';
require で、別のPHPファイルを読み込みます。
読み込むファイルは、前回作ったdb_connection.phpです。
■ db_connection.php
<?php
const DB_HOST = 'mysql:dbname=test_php;host=localhost;charset=utf8';
const DB_USER = 'php_user';
const DB_PASSWORD = 'password123';
$pdo = new PDO(DB_HOST,DB_USER,DB_PASSWORD);
//例外処理 Exception
try{
$pdo = new PDO(DB_HOST,DB_USER,DB_PASSWORD,[
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, //連想配列で返す
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //例外を表示する 必須設定
PDO::ATTR_EMULATE_PREPARES => false, //SQLインジェクション対策 必須設定
]);
echo '接続成功' ;
} catch(PDOException $e){
echo '接続失敗' . $e -> getMessage() . "\n";
exit();
}
この内容を、index.phpで読み込むということは、データベースと接続し、
接続の結果を表示するということです。
<解説②>
//ユーザー入力なしの場合 解説②
$sql = 'select * from contacts where id = 2'; //sql文
$stmt = $pdo->query($sql); //sql実行
$result = $stmt->fetchAll();
echo '<pre>';
var_dump($result);
echo '</pre>';
$sql という変数に、sql文を格納します。
その文は、'select * from contacts where id = 2' です。
$stmt という変数に、PDOのqueryというメソッドで、$sql を実行します。
つまり、データベースで実際に、'select * from contacts where id = 2'
このsql文の実行を$stmtに、格納します。
queryメソッドは、戻り値として、
PDOStatementオブジェクトを返します。
$stmt = PDOStatementオブジェクト の状態です。
$results という変数に、$stmt = PDOStatement のfetchAllメソッドを使います。
fetchAllメソッドは、データベース内の情報を配列で返します。
$results には、データベース内の情報が配列で入ります。
<表示結果>

このように、IDが2の情報が表示されます。
【 ユーザーが入力する場合 】
ユーザーが何からの情報をデーターベースから取得する場合もあります。
その場合、入力の際に、SQL文を書かれれると、データベースの情報を変更されたり、削除することができてしまいます。
これをSQLインジェクションと呼びます。
この対策をする必要があります。
<?php
//データベースと接続
require 'db_connection.php';
//ユーザー入力ありの場合
$sql = 'select * from contacts where id = :id'; //名前付きプレースホルダ 解説①
$stmt = $pdo->prepare($sql); //プリペアードステートメント 解説②
$stmt->bindValue('id', 2, PDO::PARAM_INT); //紐付け 解説③
$stmt->execute(); //実行 解説④
$result = $stmt->fetchAll();
echo '<pre>';
var_dump($result);
echo '</pre>';
<解説①>
//ユーザー入力ありの場合
$sql = 'select * from contacts where id = :id'; //名前付きプレースホルダ 解説①
$sql 変数に、sql文を格納します。その際に、id = :id と書きます。
これをプレースホルダと呼びます。
こうすることで、ユーザーの入力した値が入るように準備します。
<解説②>
//ユーザー入力ありの場合
$sql = 'select * from contacts where id = :id'; //名前付きプレースホルダ 解説①
$stmt = $pdo->prepare($sql); //プリペアードステートメント 解説②
$stmt 変数に、PDOのprepareメソッドを使用します。
queryメソッドと似たような機能で、戻り値として、
PDOStatementオブジェクトを返します。
$stmt = PDOStatement となります。
prepareメソッドは、ユーザー入力が前提の場合です。
<解説③>
//ユーザー入力ありの場合
$sql = 'select * from contacts where id = :id'; //名前付きプレースホルダ 解説①
$stmt = $pdo->prepare($sql); //プリペアードステートメント 解説②
$stmt->bindValue('id', 2, PDO::PARAM_INT); //紐付け 解説③
$stmt は 、PDOStatement が入っている音で、
PDOStatement の bindValueメソッドを使います。
bindValueメソッドは、値をパラメータにバインドします。
バインドとは、紐付けです。
引数に、
param = パラメータID
value = パラメータに紐付ける値
type = データ型の指定
を指定します。
今回の場合は、
param が 'id'
valueが'2'
typeがPDO::PARAM_INT
です。
PDO::PARAM_INTとは、SQL INTEGER データ型を表します。
INTEGERは数字です。
この処理で、id に 2 が紐付けされたことになります。
<解説④>
//ユーザー入力ありの場合
$sql = 'select * from contacts where id = :id'; //名前付きプレースホルダ 解説①
$stmt = $pdo->prepare($sql); //プリペアードステートメント 解説②
$stmt->bindValue('id', 2, PDO::PARAM_INT); //紐付け 解説③
$stmt->execute(); //実行 解説④
$stmt には、PDOStatement が入っていますから、
executeメソッドを使い、プリペアドステートメントを実行します。
プリペアドステートメントとは、<解説②>でかいた、prepareメソッドです。
<注意>
<解説③>のこのコード
$stmt->bindValue('id', 2, PDO::PARAM_INT); //紐付け 解説③
bindValueの第二引数の、2は、ユーザーの入力した値が入るので、
$nameなどの、変数が入ります。
【 まとめ 】
正直わけわからんくなってきました〜。
でも、初めはこんなもんです。
何回か挫折して、また戻ってくると、景色が変わるものであります!!