PHPで掲示板を自作しよう!【総まとめ】データベース・関数・バリデーション

PHPの学習を進めてきた皆さん、お疲れ様です。フォーム、データベース、関数、ファイル操作といった個別の技術を学んできましたね。今回は、それらの知識をすべて結集し、一つの動的なWebアプリケーション「一言掲示板」をゼロから作り上げる、総まとめ的なプロジェクトに挑戦します。

この掲示板作成を通じて、ロジック(処理)とビュー(表示)を分離するという、実践的なアプリケーション設計の基本を体験的に学びましょう。


目次

1. アプリケーションの設計

まず、アプリケーション全体の構造を設計します。今回は、役割ごとにファイルを3つに分割します。

  1. functions.php: データベース接続やHTMLエスケープなど、汎用的な便利関数をまとめたファイル。
  2. board.php: 投稿データの受け取り、バリデーション、データベースへの保存、データ取得といった、すべての**ロジック(頭脳)**を担当するファイル。
  3. 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アプリケーション「一言掲示板」が完成しました。

【このプロジェクトの重要ポイント】

  1. 関心の分離: ロジック(board.php)とビュー(view.php)を分離することで、コードが整理され、格段にメンテナンスしやすくなる。
  2. 再利用性: 汎用的な処理はfunctions.phpにまとめることで、他のプロジェクトでも再利用できる。
  3. データフロー: ユーザーのリクエスト → board.phpが処理 → view.phpが表示、という一貫したデータの流れを意識する。
  4. セキュリティ: データベースへの書き込みはプリペアドステートメント、画面への表示はhtmlspecialcharsという基本を徹底する。

この構造は、より大規模なアプリケーション開発で使われる**MVC(Model-View-Controller)**という設計思想の入り口です。ぜひこの掲示板をベースに、「編集機能」や「削除機能」を追加して、自分だけのアプリケーションに育ててみてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次