Laravelなどのフレームワークでは、クエリビルダやEloquentを使って簡単にDBから値を取ってくることができます。
今回は、PDOを使ってDB接続し、データを取ってくる流れを記載していきます。
- DBに接続(例外処理も含めて)
- SQL文の準備
- 準備したSQL文に値をバインドする
- 準備したSQLを実行する
- 実行結果を配列などで取得する
この順番で解説していきます。
1. DBに接続(例外処理も含めて)
$pdo = new PDO($dsn, $username, $password, $driver_options);
のような形で、DB接続するためのPDOインスタンスを作成します。
try {
$dbh = new PDO(
'mysql:host=サーバー名;dbname=データベース名;charset=utf8', // $dsn
'ユーザー名', // $username
'パスワード', // $password
array( // $driver_options
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // DB接続でエラーが発生したときに、PDOExceptionの例外を捕捉する
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 実行結果を配列で返すオプション
PDO::ATTR_EMULATE_PREPARES => false, // 静的プレースホルダーを使うように設定
)
);
} catch (PDOException $e) {
$error = $e->getMessage();
}
-
new PDO
で、DBに接続するためのPDOインスタンスを作成します。 -
$driver_options
の部分は、PDOで使用するoptionを指定します。 基本的には配列で指定します。PDO::ATTR_EMULATE_PREPARES
の部分は後々解説します。
2.SQL文の準備
$sql = 'SELECT * FROM article WHERE id = ?';
$prepare = $dbh->prepare($sql);
-
$sql
には、SQL文を書きます。?
の部分はプレースホルダー
になっていて、後々そこに値を割り当てます。 このような仕組みをプリペアドステートメント
というらしいです。-
?
のプレースホルダーを使用する時は、静的プレースホルダー
-
:カラム名
のプレースホルダーを使用する時は動的プレースホルダー
と言います。 - 動的プレースホルダーの方が処理速度が早いらしいですが、SQLインジェクション対策のため、基本的には静的プレースホルダーを使用することが推奨されます。
-
【PHP超入門】クラス~例外処理~PDOの基礎 - Qiita
また、
SQLインジェクション対策
にもなるため必須の方法になります。
SQLインジェクションとクエリの書き方について考える - Qiita$prepare
では、PDOのprapareメソッドを使って、SQL文を実行する準備を行っています。
3. 準備したSQL文に値をバインド(割り当て)する
bindValue(パラメータID,バインドする値,データ型)
という形でバインドします。
$prepare->bindValue(1, (int)$id, PDO::PARAM_INT);
整数型の引数を割り当てるには、(int)という形で型キャスト
をする必要があります。
【PHP入門講座】 型変換 - Qiita
整数以外は、デフォルトでPDO::PARAM_STR
が指定されます。
静的プレースホルダーの場合、パラメータIDの部分には1から始まる値を入れます。
例えば、
$sql = 'SELECT * FROM article WHERE id = ? and title = ?';
のように、?のプレースホルダーが2つある場合は、
$prepare->bindValue(1, $id, PDO::PARAM_INT);
$prepare->bindValue(2, $title, PDO::PARAM_STR);
のように、第一引数が1,2...と数字が続いていきます。
4. 準備したSQLを実行する
$sql = 'SELECT * FROM article WHERE id = ?';
$id = 1;
$prepare = $dbh->prepare($sql);
$prepare->bindValue(1, (int)$id, PDO::PARAM_INT);
$prepare->execute();
execute()メソッドでSQLを実行します。
5. 実行結果を配列などで取得する
$result = $prepare->fetchAll(PDO::FETCH_ASSOC);
fetchAll
メソッドで、条件に合致した全てのデータを配列として返します。
全体像
<?php
function dbConnect()
{
try {
$dsn = 'mysql:host=' . 'db' . '; dbname=' . 'test_php' . ';charset=utf8;';
$driver_options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
$dbh = new PDO($dsn, 'root', 'test', $driver_options);
} catch (PDOException $e) {
print('ERROR:' . $e->getMessage());
exit;
}
return $dbh;
}
function getData()
{
$dbh = dbConnect();
$sql = 'SELECT * FROM article WHERE id = ?';
$prepare = $dbh->prepare($sql);
$id = 1;
$prepare->bindValue(1, (int)$id, PDO::PARAM_INT);
$prepare->execute();
$result = $prepare->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
$result = getData(); // $result をHTML側で表示する場合は、HTML側でループして表示させます。
?>