PHPによるプログラミング(2.データベース)に関する世界観です。
PDOをnewする時のコンストラクタ引数には、「データソース名」「ユーザー名(任意)」「パスワード(任意)」「接続オプション(任意)」を指定する。
$dbh = new PDO('mysql:dbname=bbs_db;host=localhost', $db_user, $db_password);
PDOの主な関数は以下。
関数 | 説明 |
---|---|
PDO::query() | SQL文を即時に実行して結果を返す。 |
PDO::prepare() | execute()で実行されるSQL文の準備。 |
PDO::setAttribute() | データベースハンドルの属性を設定する。 PDO::ATTR_ERRMODEはエラーレポートの設定で、 PDO::ERRMODE_EXCEPTIONは例外を投げる。 PDO::ATTR_EMULATE_PREPARESは、 プリペアドステートメントのエミュレーションの有効・無効。 詳しくはPHP: PDO::setAttribute - Manualを参照。 |
PDOStatement::bindValue() | SQL文のプレースホルダに値を入れる。 |
PDOStatement::execute() | プリペアドステートメント(SQL文)の実行。 |
PDOStatement::fetchAll() | 全ての要素を含む配列を返す。 |
(【モダンなPHP】PHPでPDOを使ってMySQLに接続する方法! | CodeCampus、PDOを使ったPHPでのデータベース基本操作 - Qiitaを参考に執筆しました。)
データベースサーバーとやり取りするプログラムが、「いちばんやさしいPHPの教本 人気講師が教える実践Webプログラミング (「いちばんやさしい教本」シリーズ)」にあります。
基本的に以下のように接続すれば良い。
$dbh = new PDO('mysql:dbname=bbs_db;host=localhost;charset=utf8', $db_user, $db_password); $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "SELECT * FROM bbs"; $stmt = $dbh->query($sql); $data = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($data as $row) { /*HTML表示などの処理*/ }
(以上は「いちばんやさしいPHPの教本 人気講師が教える実践Webプログラミング (「いちばんやさしい教本」シリーズ)」より編集して部分的に引用。)
foreach文「foreach ($data as $row) {}」の中で、ひとつひとつのデータ(行の中の列の項目)には
$row['username']
や
$row['comment']
のようにアクセスする。
セキュリティ対策のために
htmlspecialchars($row['username'], ENT_QUOTES, 'UTF-8')
とするのが望ましい。
たとえば、
echo "<table>\n"; foreach ($data as $row) { echo "<tr>"; echo "<td>"; echo htmlspecialchars($row['username'], ENT_QUOTES, 'UTF-8'); echo "</td>"; echo "<td>"; echo htmlspecialchars($row['comment'], ENT_QUOTES, 'UTF-8'); echo "</td>"; echo "</tr>\n"; } echo "</table>\n";
などとする。
(以上は「いちばんやさしいPHPの教本 人気講師が教える実践Webプログラミング (「いちばんやさしい教本」シリーズ)」より編集して部分的に引用。)
以下はプレースホルダの例。
以下の?のところに変数の値が入る。
$sql = "SELECT * FROM bbs WHERE uid = ?"
これに対して、PHPでは
bindValue(?の出てくる番号, ?に入れる変数, 型)
として、?に値を設定する。たとえば、
$stmt = $dbh->prepare($sql); $stmt->bindValue(1, $user_id, PDO::PARAM_INT); $stmt->execute();のようにする(1が1番目の?に対応し、$user_idを当てはめる)。
(以上は「いちばんやさしいPHPの教本 人気講師が教える実践Webプログラミング (「いちばんやさしい教本」シリーズ)」を参考に執筆しました。)
プレースホルダはprepare()の時にbindValue()ではなくbindParam()を使うことで名前を付けて変換することもできる。プレースホルダ名には:idのように「:」をつけて表現する。
$stmt = $dbh->prepare('INSERT INTO bbs(uid, comment) VALUES(:uid, :comment)'; $stmt->bindParam(':uid', $user_id); $stmt->bindParam(':comment', $_POST['comment']); $stmt->execute();
などとする。
(以上は3ステップでしっかり学ぶ MySQL入門 (今すぐ使えるかんたんプラス)より編集して部分的に引用。)
SELECT文だけではなく、INSERT、UPDATE、DELETEなどの命令文(CRUD操作)も同様にプリペアドステートメントにSQL文を代入して実行できる。
SELECTの場合:
$sql = "SELECT * FROM bbs"; $stmt = $dbh->query($sql); $data = $stmt->fetchAll(PDO::FETCH_ASSOC);
INSERTの場合:
$sql = "INSERT INTO bbs (name,email,text) VALUES (?, ?, ?)"; $stmt = $dbh->prepare($sql); $stmt->bindValue(1, $name, PDO::PARAM_STR); $stmt->bindValue(2, $email, PDO::PARAM_STR); $stmt->bindValue(3, $text, PDO::PARAM_STR); $stmt->execute();
UPDATEの場合:
$sql = "UPDATE bbs SET text = ?, name = ? WHERE id = ?"; $stmt = $dbh->prepare($sql); $stmt->bindValue(1, $text, PDO::PARAM_STR); $stmt->bindValue(2, $name, PDO::PARAM_STR); $stmt->bindValue(3, $id, PDO::PARAM_INT); $stmt->execute();
DELETEの場合:
$sql = "DELETE FROM bbs WHERE id = ?"; $stmt = $dbh->prepare($sql); $stmt->bindValue(1, $id, PDO::PARAM_INT); $stmt->execute();
PDOオブジェクトの詳しい使い方については以下が参考になる。
以下の書籍が参考になります。
また、MySQLしかデータベースサーバーを使わないのであれば、mysql_connect()やmysql_query()などのようなmysql_*系の関数を使うこともできます。
以下はPHPとMySQLの連携について。
MySQLも参照のこと。
PHPからデータベースを操作できるPDOクラスですが、実際には上から下へと流れるように書くのではなく、DbManagerのような専門のクラスを仲介することが多いです。
DbManagerという名前のクラスにおいて、new PDO()したオブジェクトをメンバとして保持するようにし、このオブジェクトに対して外部からさまざまなメソッドを実行し、その中でSQL文をクエリ実行するようにします。
もし、ページごとにPDOを操作していると、ひとつのページで一回しかデータベース処理することができず、複雑なことができません。
DbManagerのような専門のクラスを用意することで、さまざまな場所からさまざまなタイミングで、データベースを処理することができます。
(詳しくはパーフェクトPHP (PERFECT SERIES 3)を参照してください。)
2023.05.15