URLからIDを受け取り、そのIDを使ってデータベースから特定のレコードを取得する準備が整いました。最後のステップは、取得したデータをHTMLに埋め込み、ユーザーに見やすい「詳細ページ」として完成させることです。
この記事では、PDOで取得した一行分のデータを、PHPのecho
とhtmlspecialchars()
を使い、安全にWebページに表示する具体的な方法を解説します。
1. 1件のデータを取得するfetch()
メソッドの確認
まず、特定のIDを持つレコード1件だけを取得する流れをおさらいしましょう。
prepare()
でWHERE id = ?
という条件付きのSQL文を準備する。execute([$id])
で、安全な形でIDをSQL文に渡して実行する。fetch(PDO::FETCH_ASSOC)
で、結果セットから最初の1行だけを連想配列として取得する。
この結果、変数(例: $review
)には、以下のような単一の連想配列が格納されます。
// $review の中身のイメージ
[
'id' => 5,
'book_title' => 'SQL実践入門',
'rating' => 4,
'review_text' => "サンプルが多くて分かりやすい。\n実践的な内容だった。"
]
この連想配列のキー(book_title
など)を使って、各データにアクセスします。
レコードが見つからなかった場合の考慮
もしURLで指定されたID(例: id=999
)がデータベースに存在しなかった場合、fetch()
メソッドはレコードを見つけられず、**false
**を返します。この「データが存在しない」というケースを考慮しないと、エラーの原因になります。
2. 取得したデータをHTMLに表示する
取得した連想配列の値をHTMLに表示するには、echo
を使い、キーを指定して値を取り出します。
基本の書き方: echo $review['book_title'];
そして、セキュリティの観点から絶対に忘れてはならないのが、htmlspecialchars()
によるエスケープ処理です。ユーザーが入力したデータだけでなく、データベースから取得したデータであっても、画面に出力する際は必ずこの処理を行い、XSS(クロスサイトスクリプティング)攻撃を防ぎましょう。
安全な書き方: echo htmlspecialchars($review['book_title'], ENT_QUOTES, 'UTF-8');
3. 完成版コード:動的な詳細ページの作成
それでは、これまでの知識を総動員して、IDのバリデーションからデータの取得、表示、そして「データが見つからなかった場合」の処理までを実装した、完全な詳細ページのサンプルコードを見てみましょう。
detail.php
のサンプルコード:
<?php
// --- データベース接続設定 ---
$dsn = 'mysql:host=localhost;dbname=my_first_db;charset=utf8mb4';
$user = 'root';
$password = 'root'; // ご自身の環境に合わせて変更してください
// --- 初期化 ---
$review = null;
$error_message = '';
try {
// --- IDのバリデーション ---
if (empty($_GET['id']) || !ctype_digit($_GET['id'])) {
throw new Exception('IDが不正です。');
}
$id = (int)$_GET['id'];
// --- データベース処理 ---
$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = "SELECT * FROM reviews WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute([$id]);
$review = $stmt->fetch(PDO::FETCH_ASSOC);
// --- レコード存在チェック ---
if (!$review) {
throw new Exception('指定されたレビューは見つかりませんでした。');
}
} catch (Exception $e) {
// エラーメッセージを$error_messageに格納
$error_message = $e->getMessage();
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>読書レビュー詳細</title>
</head>
<body>
<?php if ($error_message): ?>
<h1>エラー</h1>
<p><?php echo htmlspecialchars($error_message, ENT_QUOTES, 'UTF-8'); ?></p>
<a href="list.php">一覧に戻る</a>
<?php else: ?>
<h1><?php echo htmlspecialchars($review['book_title'], ENT_QUOTES, 'UTF-8'); ?></h1>
<dl>
<dt>評価:</dt>
<dd><?php echo htmlspecialchars($review['rating'], ENT_QUOTES, 'UTF-8'); ?> / 5</dd>
<dt>感想:</dt>
<dd><?php echo nl2br(htmlspecialchars($review['review_text'], ENT_QUOTES, 'UTF-8')); ?></dd>
<dt>登録日時:</dt>
<dd><?php echo htmlspecialchars($review['created_at'], ENT_QUOTES, 'UTF-8'); ?></dd>
</dl>
<a href="list.php">一覧に戻る</a>
<?php endif; ?>
</body>
</html>
コードのポイント:
- エラーハンドリング:
try...catch
ブロックを使い、IDの不正やデータが見つからない場合のエラーメッセージを$error_message
変数に格納しています。 - 条件付きレンダリング: PHPの
if/else
構文を使い、$error_message
に何か入っている(=エラーがあった)場合はエラー表示を、そうでなければ(=正常に$review
が取得できた)詳細情報を表示するように、HTMLの出力を切り替えています。 - 安全な出力: 表示するすべての動的データ(
$error_message
と$review
の各要素)は、htmlspecialchars()
でエスケープしています。
まとめ
fetch(PDO::FETCH_ASSOC)
で取得した単一レコード(連想配列)から、キー(カラム名)を指定して値を取り出す。fetch()
がfalse
を返す(=データが見つからない)場合に備え、エラー処理を実装する。- PHPの
if/else
構文とHTMLを組み合わせることで、正常時とエラー時で表示内容を動的に切り替えることができる。 - データベースから取得した値であっても、画面に出力する際は必ず
htmlspecialchars()
を使う。
この一連の処理は、Webアプリケーションにおける最も基本的ながら、最も重要なデータ表示のパターンです。この構造をマスターすれば、どんなデータでも安全に詳細ページとして表示できるようになります。