PHPの学習を進めてきた皆さん、お疲れ様です。フォーム、データベース、関数、ファイル操作といった個別の技術を学んできましたね。今回は、それらの知識をすべて結集し、一つの動的なWebアプリケーション「一言掲示板」をゼロから作り上げる、総まとめ的なプロジェクトに挑戦します。
この掲示板作成を通じて、ロジック(処理)とビュー(表示)を分離するという、実践的なアプリケーション設計の基本を体験的に学びましょう。
1. アプリケーションの設計
まず、アプリケーション全体の構造を設計します。今回は、役割ごとにファイルを3つに分割します。
functions.php
: データベース接続やHTMLエスケープなど、汎用的な便利関数をまとめたファイル。board.php
: 投稿データの受け取り、バリデーション、データベースへの保存、データ取得といった、すべての**ロジック(頭脳)**を担当するファイル。view.php
:board.php
から渡されたデータをもとに、HTMLを生成して画面を**表示(顔)**することに専念するファイル。
このように役割を分離することで、コードの見通しが良くなり、修正や機能追加がしやすくなります。
2. データベースと関数の準備
2.1. テーブルの作成
投稿された名前、コメント、日時を保存するためのposts
テーブルをphpMyAdminで作成します。
【posts
テーブルの構造】 | カラム名 | データ型 | その他 | | :— | :— | :— | | id
| INT | AUTO_INCREMENT, PRIMARY KEY | | author_name
| VARCHAR(50) | | | comment
| TEXT | | | created_at
| DATETIME | |
2.2. functions.php
の拡充
これまでに作成した便利関数に、掲示板用の関数を追加します。
【functions.php
】
<?php
// (h(), get_post(), get_db_connection(), validate_length() などは前章から流用)
function h(string $str): string { /* ... */ }
function get_db_connection(): PDO { /* ... */ }
// ...
/**
* 投稿をデータベースに挿入する関数
* @param PDO $dbh DBハンドラ
* @param string $name 名前
* @param string $comment コメント
* @return bool 成功/失敗
*/
function addPost(PDO $dbh, string $name, string $comment): bool
{
// NOW() を使ってデータベースサーバーの現在時刻を記録
$sql = "INSERT INTO posts (author_name, comment, created_at) VALUES (:name, :comment, NOW())";
try {
$stmt = $dbh->prepare($sql);
$stmt->bindValue(':name', $name, PDO::PARAM_STR);
$stmt->bindValue(':comment', $comment, PDO::PARAM_STR);
return $stmt->execute();
} catch (PDOException $e) {
// エラー発生時はfalseを返す
return false;
}
}
/**
* 全ての投稿を取得する関数
* @param PDO $dbh DBハンドラ
* @return array 投稿データの配列
*/
function getAllPosts(PDO $dbh): array
{
$sql = "SELECT id, author_name, comment, created_at FROM posts ORDER BY id DESC";
// DESCで新しい投稿が上にくるように並び替え
return $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
}
3. board.php
– アプリケーションの頭脳(ロジック)
このファイルがアプリケーションの中心です。ユーザーからの入力を処理し、データベースとやり取りを行いますが、一切HTMLを出力しないのがポイントです。
【board.php
】
<?php
// 関数ファイルを読み込む
require_once 'functions.php';
// 変数の初期化
$errors = [];
$name = '';
$comment = '';
// データベースに接続
$dbh = get_db_connection();
// --- POSTリクエスト処理 ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// POSTされたデータを取得
$name = get_post('name');
$comment = get_post('comment');
// バリデーション
if (empty($name)) {
$errors[] = 'お名前を入力してください。';
} elseif (mb_strlen($name) > 50) {
$errors[] = 'お名前は50文字以内で入力してください。';
}
if (empty($comment)) {
$errors[] = 'コメントを入力してください。';
} elseif (mb_strlen($comment) > 200) {
$errors[] = 'コメントは200文字以内で入力してください。';
}
// エラーがなければデータベースに挿入
if (empty($errors)) {
if (!addPost($dbh, $name, $comment)) {
$errors[] = 'データベースへの書き込みに失敗しました。';
} else {
// 成功したら自分自身にリダイレクトして、POSTの再送信を防ぐ (PRGパターン)
header('Location: board.php');
exit;
}
}
}
// --- データベースから全投稿を取得 ---
$posts = getAllPosts($dbh);
// --- ビュー(HTML)を読み込む ---
// board.phpで定義された変数は、view.php内でそのまま使える
include_once 'view.php';
4. view.php
– アプリケーションの顔(表示)
このファイルは、board.php
から渡された変数($errors
, $name
, $comment
, $posts
)を使って、HTMLを描画することだけに責任を持ちます。
【view.php
】
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>一言掲示板</title>
<style>
body { font-family: sans-serif; }
.container { max-width: 700px; margin: 30px auto; }
.post-form { border: 1px solid #ccc; padding: 20px; margin-bottom: 20px; }
.post-list { border-top: 1px solid #ccc; }
.post-item { border-bottom: 1px solid #ccc; padding: 15px 0; }
.post-item .author { font-weight: bold; }
.post-item .date { color: #888; font-size: 0.9em; }
.error-list { color: #d9534f; border: 1px solid #d9534f; padding: 10px; margin-bottom: 15px;}
</style>
</head>
<body>
<div class="container">
<h1>一言掲示板</h1>
<?php if (!empty($errors)): ?>
<div class="error-list">
<ul>
<?php foreach ($errors as $error): ?>
<li><?php echo h($error); ?></li>
<?php endforeach; ?>
</ul>
</div>
<?php endif; ?>
<div class="post-form">
<form action="" method="POST">
<p>
<label for="name">お名前 (50文字以内):</label><br>
<input type="text" id="name" name="name" value="<?php echo h($name); ?>">
</p>
<p>
<label for="comment">コメント (200文字以内):</label><br>
<textarea id="comment" name="comment" rows="4" cols="50"><?php echo h($comment); ?></textarea>
</p>
<input type="submit" value="投稿する">
</form>
</div>
<div class="post-list">
<?php if (!empty($posts)): ?>
<?php foreach ($posts as $post): ?>
<div class="post-item">
<p class="author">名前: <?php echo h($post['author_name']); ?></p>
<p><?php echo nl2br(h($post['comment'])); ?></p>
<p class="date">投稿日時: <?php echo h($post['created_at']); ?></p>
</div>
<?php endforeach; ?>
<?php else: ?>
<p>まだ投稿はありません。</p>
<?php endif; ?>
</div>
</div>
</body>
</html>
まとめ
お疲れ様でした! これで、PHPの基本的な要素が詰まった動的なWebアプリケーション「一言掲示板」が完成しました。
【このプロジェクトの重要ポイント】
- 関心の分離: ロジック(
board.php
)とビュー(view.php
)を分離することで、コードが整理され、格段にメンテナンスしやすくなる。 - 再利用性: 汎用的な処理は
functions.php
にまとめることで、他のプロジェクトでも再利用できる。 - データフロー: ユーザーのリクエスト →
board.php
が処理 →view.php
が表示、という一貫したデータの流れを意識する。 - セキュリティ: データベースへの書き込みはプリペアドステートメント、画面への表示は
htmlspecialchars
という基本を徹底する。
この構造は、より大規模なアプリケーション開発で使われる**MVC(Model-View-Controller)**という設計思想の入り口です。ぜひこの掲示板をベースに、「編集機能」や「削除機能」を追加して、自分だけのアプリケーションに育ててみてください。