はじめに
これまでのステップで、PHPの基本的な文法、フォーム処理、データベース操作などを学んできました。いよいよ実践編です!💪 このステップでは、学んだ知識を総動員して、簡単な掲示板アプリを作成します。
この掲示板アプリでは、以下の機能を実現します。
- 名前とメッセージを投稿できるフォーム
- 投稿された名前とメッセージを一覧表示する機能
シンプルな機能ですが、Webアプリケーション開発の基本要素が詰まっています。さっそく挑戦してみましょう!🚀
1. データベースの準備 💾
まずは、投稿されたメッセージを保存するためのデータベースとテーブルを準備します。phpMyAdminなどのツールを使って、新しいデータベース(例: `php_bbs`)を作成し、その中に以下の構造を持つテーブル(例: `posts`)を作成しましょう。
カラム名 | データ型 | 制約 | 説明 |
---|---|---|---|
id | INT | UNSIGNED AUTO_INCREMENT PRIMARY KEY | 投稿ID (自動採番) |
name | VARCHAR(50) | NOT NULL | 投稿者名 |
message | TEXT | NOT NULL | メッセージ本文 |
created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | 投稿日時 |
SQLでテーブルを作成する場合は、以下のようになります。
CREATE TABLE posts (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. データベース接続設定 ⚙️
次に、PHPからデータベースに接続するための設定ファイルを作成します。config.php
という名前でファイルを作成し、以下のようにデータベース接続情報を記述します。(実際の接続情報に合わせてください)
<?php
define('DB_HOST', 'localhost'); // データベースサーバーのホスト名
define('DB_NAME', 'php_bbs'); // データベース名
define('DB_USER', 'your_db_username'); // データベースユーザー名
define('DB_PASS', 'your_db_password'); // データベースパスワード
// データベース接続オプション
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // エラーモードを例外に設定
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // フェッチモードを連想配列に設定
PDO::ATTR_EMULATE_PREPARES => false, // プリペアドステートメントのエミュレーションを無効化
];
// データソース名 (DSN)
$dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4";
try {
// PDOインスタンスの作成
$pdo = new PDO($dsn, DB_USER, DB_PASS, $options);
} catch (PDOException $e) {
// 接続エラー時の処理
die("データベース接続に失敗しました: " . $e->getMessage());
}
?>
このファイルは、データベース操作が必要な他のPHPファイルから読み込んで使用します。
3. 掲示板のメインファイル作成 (index.php) 📄
いよいよ掲示板のメインとなるファイル `index.php` を作成します。このファイルは、投稿フォームの表示、投稿処理、投稿一覧の表示を担当します。
3.1. ファイルの基本構造と設定ファイルの読み込み
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>簡単掲示板</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css"> <!-- Bulma CSS -->
</head>
<body>
<section class="section">
<div class="container">
<h1 class="title">📝 簡単掲示板</h1>
<?php
// データベース接続設定ファイルを読み込む
require_once 'config.php';
// エラーメッセージ格納用変数
$errors = [];
// 成功メッセージ格納用変数
$success_message = '';
// --- ここに投稿処理を記述 ---
// --- ここに投稿一覧表示処理を記述 ---
?>
<!-- 投稿フォーム -->
<div class="box mt-5">
<h2 class="subtitle is-5">メッセージを投稿する</h2>
<?php // エラーメッセージの表示
if (!empty($errors)): ?>
<div class="notification is-danger is-light">
<ul>
<?php foreach ($errors as $error): ?>
<li><?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8'); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<?php // 成功メッセージの表示
if (!empty($success_message)): ?>
<div class="notification is-success is-light">
<?php echo htmlspecialchars($success_message, ENT_QUOTES, 'UTF-8'); ?>
</div>
<?php endif; ?>
<form action="index.php" method="post">
<div class="field">
<label class="label" for="name">お名前</label>
<div class="control">
<input class="input" type="text" id="name" name="name" required>
</div>
</div>
<div class="field">
<label class="label" for="message">メッセージ</label>
<div class="control">
<textarea class="textarea" id="message" name="message" rows="3" required></textarea>
</div>
</div>
<div class="field">
<div class="control">
<button class="button is-primary" type="submit">投稿する</button>
</div>
</div>
</form>
</div>
<!-- /投稿フォーム -->
<!-- 投稿一覧 -->
<div class="mt-5">
<h2 class="subtitle is-5">投稿一覧</h2>
<div id="post-list">
<!-- ここに投稿一覧が表示される -->
</div>
</div>
<!-- /投稿一覧 -->
</div>
</section>
</body>
</html>
まずはHTML部分と、設定ファイルの読み込み、メッセージ表示用の変数を準備します。フォームの `action` 属性は `index.php`(自分自身)、`method` 属性は `post` に設定します。
3.2. 投稿処理の実装 (POSTリクエストの処理)
フォームからデータが送信された (POSTリクエストが来た) 場合の処理を記述します。場所は `// — ここに投稿処理を記述 —` の部分です。
// --- ここに投稿処理を記述 ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// フォームからのデータを取得し、サニタイズ
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
$message = isset($_POST['message']) ? trim($_POST['message']) : '';
// 簡単なバリデーション
if ($name === '') {
$errors[] = 'お名前を入力してください。';
} elseif (mb_strlen($name) > 50) {
$errors[] = 'お名前は50文字以内で入力してください。';
}
if ($message === '') {
$errors[] = 'メッセージを入力してください。';
}
// エラーがない場合のみデータベースに挿入
if (empty($errors)) {
try {
// プリペアドステートメントを使用して安全にデータを挿入
$sql = "INSERT INTO posts (name, message) VALUES (:name, :message)";
$stmt = $pdo->prepare($sql);
$stmt->bindParam(':name', $name, PDO::PARAM_STR);
$stmt->bindParam(':message', $message, PDO::PARAM_STR);
// SQLを実行
if ($stmt->execute()) {
$success_message = 'メッセージを投稿しました!🎉';
// フォームの再送信を防ぐためにリダイレクト(任意)
// header('Location: index.php');
// exit;
} else {
$errors[] = '投稿に失敗しました。もう一度お試しください。';
}
} catch (PDOException $e) {
$errors[] = 'データベースエラー: ' . $e->getMessage();
// 本番環境では詳細なエラーメッセージをユーザーに見せないように注意
// error_log('PDO Error: ' . $e->getMessage()); // エラーログに記録
// $errors[] = 'データベースエラーが発生しました。';
}
}
}
// --- 投稿処理 ここまで ---
POSTリクエストかどうかを確認し、送信されたデータを `$_POST` スーパーグローバル変数から取得します。`trim()` で前後の空白を除去し、簡単なバリデーション(空チェック、文字数チェック)を行います。
エラーがなければ、PDOを使ってデータベースにデータを挿入します。SQLインジェクション対策として、必ずプリペアドステートメント (`prepare`, `bindParam`, `execute`) を使用しましょう。
投稿成功時には成功メッセージを設定します。コメントアウトされている `header()` 関数を使うと、投稿後にページをリダイレクトさせ、ブラウザの更新ボタンによる意図しない再投稿(二重投稿)を防ぐことができます(今回はシンプルにするためリダイレクトは行いません)。
3.3. 投稿一覧表示処理の実装
次に、データベースから投稿データを取得し、一覧表示する処理を記述します。場所は `// — ここに投稿一覧表示処理を記述 —` の部分です。
// --- ここに投稿一覧表示処理を記述 ---
try {
// postsテーブルからデータを新しい順に取得
$sql_select = "SELECT name, message, created_at FROM posts ORDER BY created_at DESC";
$stmt_select = $pdo->query($sql_select); // クエリを実行
$posts = $stmt_select->fetchAll(); // 結果をすべて取得
} catch (PDOException $e) {
// エラー発生時はエラーメッセージを表示して処理を中断
echo '<div class="notification is-danger">投稿の読み込みに失敗しました: ' . htmlspecialchars($e->getMessage(), ENT_QUOTES, 'UTF-8') . '</div>';
$posts = []; // エラー時は空の配列にする
// ここで処理を中断する場合は exit; などを使用
}
// --- 投稿一覧表示処理 ここまで ---
`SELECT` 文で `posts` テーブルから必要なカラム (`name`, `message`, `created_at`) を取得します。`ORDER BY created_at DESC` で新しい投稿が上に表示されるように並び替えます。 取得したデータは `$posts` 配列に格納します。
最後に、取得した投稿データをHTMLとして表示する部分(`<div id=”post-list”>` の中)を修正します。
<!-- 投稿一覧 -->
<div class="mt-5">
<h2 class="subtitle is-5">投稿一覧</h2>
<div id="post-list">
<?php if (empty($posts)): ?>
<p>まだ投稿はありません。</p>
<?php else: ?>
<?php foreach ($posts as $post): ?>
<article class="message is-info mb-4">
<div class="message-header">
<p>
<strong><?php echo htmlspecialchars($post['name'], ENT_QUOTES, 'UTF-8'); ?></strong>
<small class="ml-2">(<?php echo htmlspecialchars($post['created_at'], ENT_QUOTES, 'UTF-8'); ?>)</small>
</p>
</div>
<div class="message-body">
<?php echo nl2br(htmlspecialchars($post['message'], ENT_QUOTES, 'UTF-8')); ?>
</div>
</article>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<!-- /投稿一覧 -->
`$posts` 配列を `foreach` でループし、各投稿を表示します。ここで重要なのは、ユーザーが入力した内容(名前やメッセージ)をHTMLに出力する際に、必ず `htmlspecialchars()` 関数を使ってXSS(クロスサイトスクリプティング)対策を行うことです。これにより、悪意のあるHTMLタグやJavaScriptコードが埋め込まれるのを防ぎます。
また、メッセージ本文は改行がそのまま表示されるように `nl2br()` 関数も併用しています。
4. 実行してみよう! ▶️
これで、`config.php` と `index.php` の2つのファイルが完成しました。これらのファイルをWebサーバー(XAMPPやMAMPのhtdocs/wwwディレクトリなど)に配置し、Webブラウザから `index.php` にアクセスしてみてください。
フォームが表示され、名前とメッセージを入力して投稿すると、下に一覧表示されるはずです。🎉
まとめと次のステップ ✨
お疲れ様でした!簡単な掲示板アプリを作成することで、PHPによるWebアプリケーション開発の一連の流れを体験できましたね。
- HTMLフォームの作成
- POSTデータの受け取りと処理
- データベースへの接続と操作 (PDO, プリペアドステートメント)
- データベースからのデータ取得と表示
- 基本的なセキュリティ対策 (XSS対策, SQLインジェクション対策)
これらの要素は、より複雑なWebアプリケーションを開発する上での基礎となります。
今回作成した掲示板は非常にシンプルですが、ここからさらに機能を拡張していくことができます。例えば…
- 投稿の編集・削除機能
- パスワードによる投稿の保護
- ページネーション(投稿が多い場合にページを分ける)
- 画像のアップロード機能
次のステップでは、ログイン機能の実装に挑戦してみましょう! 💪
コメント