View on GitHub

technote

✅ 投稿後に Location: ヘッダでリダイレクトする。

✅ なぜリダイレクトするのか?

🔁 再送信防止(Post/Redirect/Get パターン)


✅ 修正後の全コード(bbs_mysql.php)

<?php
// --- データベース接続 ---
$dsn = 'mysql:host=localhost;dbname=bbs_db;charset=utf8mb4';
$user = 'your_username';
$pass = 'your_password';

try {
    $pdo = new PDO($dsn, $user, $pass);
} catch (PDOException $e) {
    exit("DB接続エラー: " . $e->getMessage());
}

// --- 投稿処理 ---
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');
    $message = trim($_POST['message'] ?? '');

    if ($name !== '' && $message !== '') {
        $stmt = $pdo->prepare("INSERT INTO posts (name, message) VALUES (:name, :message)");
        $stmt->execute([
            ':name' => $name,
            ':message' => $message
        ]);

        // --- ここでリダイレクト ---
        header("Location: " . $_SERVER['PHP_SELF']);
        exit(); // 重要!このあと出力しないようにする
    }
}

// --- 投稿一覧の取得(GET時) ---
$stmt = $pdo->query("SELECT * FROM posts ORDER BY created_at DESC");
$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>MySQL掲示板(リダイレクト対応)</title>
</head>
<body>
  <h1>MySQL掲示板</h1>

  <form method="post" action="">
    <p>
      名前:<br>
      <input type="text" name="name" required>
    </p>
    <p>
      メッセージ:<br>
      <textarea name="message" rows="4" cols="40" required></textarea>
    </p>
    <p><input type="submit" value="投稿"></p>
  </form>

  <hr>

  <h2>投稿一覧</h2>
  <ul>
    <?php foreach ($posts as $post): ?>
      <li>
        <strong><?php echo htmlspecialchars($post['created_at'], ENT_QUOTES, 'UTF-8'); ?></strong><br>
        <strong><?php echo htmlspecialchars($post['name'], ENT_QUOTES, 'UTF-8'); ?></strong>
        <?php echo nl2br(htmlspecialchars($post['message'], ENT_QUOTES, 'UTF-8')); ?>
      </li>
      <hr>
    <?php endforeach; ?>
  </ul>
</body>
</html>

✅ 変更点まとめ

修正ポイント 内容
header(“Location: …”) POST成功後、同じファイルにGETで再アクセスさせる
exit(); の追加 リダイレクト後にHTML出力が走らないようにするため(必須!)
$_SERVER[‘PHP_SELF’] 現在のファイル自身のパス(たとえば /bbs_mysql.php)

📌 補足:リダイレクトしないと… リロード時にブラウザから警告が出る:

このページを再度表示すると、フォームに入力された情報が再送信されます。 これを防ぐのがPost/Redirect/Getの基本パターンです。


環境:

この場合における 推奨DB接続コード(PDO使用)とその理由 を解説します。

✅ 推奨コード(PHP 5.6 + MySQL/MariaDB 10.11対応)

<?php
$dsn = 'mysql:host=localhost;dbname=your_db_name;charset=utf8';
$user = 'your_username';
$pass = 'your_password';

try {
    $pdo = new PDO($dsn, $user, $pass, [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,         // 例外でエラー通知
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,    // 連想配列で取得
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"     // 初期文字コード設定(PHP 5.6向け)
    ]);
} catch (PDOException $e) {
    die('データベース接続失敗: ' . $e->getMessage());
}
?>

✅ 推奨理由

項目 内容 なぜ推奨?
PDOを使用 new PDO(…) mysqli より汎用性が高く、後のバージョン移行にも対応しやすい
エラーモード指定 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION SQLエラー時に try-catch で補足しやすく、バグに気づきやすい
文字コード設定 SET NAMES utf8 明示 PHP 5.6では charset=utf8 だけでは不十分なことがあるため安全のために設定
FETCHモード指定 PDO::FETCH_ASSOC 結果の配列が読みやすくなる(連想配列のみ)
例外補足 try-catch を使用 接続失敗時に丁寧なエラーメッセージを出せる

⚠ 注意点(PHP 5.6 + MariaDB 10.11)

✅ 文字コードの補足(重要) PHP 5.6 時代は charset=utf8 を DSN に書くだけでは、 実際の接続時に utf8 が使われないケースがあるため、SET NAMES を使うのが安全策です。


✅ まとめ:PHP 5.6での安全なDB接続には