見出し画像

【 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の第二引数の、は、ユーザーの入力した値が入るので、
$nameなどの、変数が入ります。



【 まとめ 】

正直わけわからんくなってきました〜。

でも、初めはこんなもんです。

何回か挫折して、また戻ってくると、景色が変わるものであります!!

この記事が気に入ったらサポートをしてみませんか?