【PHP応用-4】投稿を削除したい!SQLのDELETE文と「hidden」タグの使い方

PHPコース、いよいよ最終回です。
前回作った掲示板に、間違えて投稿したメッセージを消すための「削除ボタン」をつけましょう。

ここで重要なのは、「どうやって消したい投稿だけをピンポイントで指名するか?」です。

データを消す命令「DELETE」

データを削除するには、SQLの DELETE 文を使います。

⚠️ 恐怖の落とし穴

-- ❌ これをやると全部消える!!
DELETE FROM messages

条件を指定しないと、テーブルの中身が空っぽになってしまいます。
必ず WHERE(ホウェア) を使って、「idが〇〇のやつだけ」と指定します。

-- ⭕️ idが5番のデータだけ消す
DELETE FROM messages WHERE id = 5

どのボタンが押されたか判別する「hidden」

画面には投稿がズラッと並んでいます。
どの「削除ボタン」が押されたのかをPHPに伝えるために、HTMLの type="hidden" を使います。

これは「画面には見えないけれど、データとして送信される入力欄」です。
ここに、投稿ごとの「ID」をこっそり仕込んでおくのです。

<form method="post">
    <!-- 画面には出さずにIDを送る -->
    <input type="hidden" name="delete_id" value="5">
    <button type="submit">削除</button>
</form>

実践:削除機能付き掲示板

では、前回の bbs.php を改造して、削除機能を実装しましょう。

<?php
    // DB接続(共通)
    $dsn = 'mysql:dbname=bbs_app;host=localhost;charset=utf8mb4';
    $user = 'root';
    $password = ''; // MAMPは 'root'

    try {
        $pdo = new PDO($dsn, $user, $password);

        // === 削除ボタンが押された時 ===
        // hiddenで送られた "delete_id" があるかチェック
        if (isset($_POST['delete_id'])) {
            $delete_id = $_POST['delete_id'];
            
            // 指定されたIDを削除するSQL
            $sql = "DELETE FROM messages WHERE id = :id";
            $stmt = $pdo->prepare($sql);
            $stmt->bindValue(':id', $delete_id, PDO::PARAM_INT);
            $stmt->execute();
        }

        // === 新規投稿が押された時 ===
        if (isset($_POST['username'])) {
            $username = $_POST['username'];
            $comment  = $_POST['comment'];
            $sql = "INSERT INTO messages (username, comment, created_at) VALUES (:username, :comment, NOW())";
            $stmt = $pdo->prepare($sql);
            $stmt->bindValue(':username', $username, PDO::PARAM_STR);
            $stmt->bindValue(':comment', $comment, PDO::PARAM_STR);
            $stmt->execute();
        }

        // === 一覧表示(常に実行) ===
        $sql = "SELECT * FROM messages ORDER BY id DESC";
        $stmt = $pdo->query($sql);
        $messages = $stmt->fetchAll();

    } catch (PDOException $e) {
        echo "エラー: " . $e->getMessage();
        exit;
    }
?>

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ひとこと掲示板</title>
    <style>
        .post { border-bottom: 1px solid #ddd; padding: 10px; display: flex; justify-content: space-between; }
        .delete-btn { color: red; cursor: pointer; background: none; border: none; text-decoration: underline; }
    </style>
</head>
<body>

    <h1>ひとこと掲示板</h1>

    <form action="" method="post">
        名前:<input type="text" name="username" required>
        本文:<input type="text" name="comment" required>
        <button type="submit">投稿</button>
    </form>
    <hr>

    <?php foreach ($messages as $msg): ?>
        <div class="post">
            <div>
                <strong><?= htmlspecialchars($msg['username'], ENT_QUOTES, 'UTF-8') ?></strong>
                :<?= htmlspecialchars($msg['comment'], ENT_QUOTES, 'UTF-8') ?>
                <small>(<?= htmlspecialchars($msg['created_at'], ENT_QUOTES, 'UTF-8') ?>)</small>
            </div>
            
            <!-- 削除ボタン(投稿ごとに小さなフォームを作る) -->
            <form action="" method="post" onsubmit="return confirm('本当に削除しますか?');">
                <!-- どのIDを消すかを、画面に出さずに送る -->
                <input type="hidden" name="delete_id" value="<?= $msg['id'] ?>">
                <button type="submit" class="delete-btn">削除</button>
            </form>
        </div>
    <?php endforeach; ?>

</body>
</html>

解説:削除の流れ

  1. 一覧表示のループの中で、投稿ごとに小さな <form> を作っています。
  2. その中に <input type="hidden" value="<?= $msg['id'] ?>"> を入れています。これで、「田中さんの投稿(ID:5)」には「5」、「佐藤さんの投稿(ID:6)」には「6」が埋め込まれます。
  3. 削除ボタンを押すと、そのIDだけがPHPに送信され、DELETE 文で削除されます。

⚠️ hidden は「隠す」であって「秘密にする」ではありません

hidden で送った値は、ブラウザの検証ツールを開けば誰でも見られますし、書き換えることもできます。つまりこのコードのままだと、IDを書き換えて他人の投稿を消すことができてしまいます。

この記事では仕組みを理解することを優先して省いていますが、本番では「消していいのはこの人か」をサーバー側で必ず確認します。あわせてCSRF対策も必要です。

もう一点。エラーの内容($e->getMessage())をそのまま画面に出しているのも学習用です。本番ではデータベース名などが表示されてしまうので、画面には「エラーが発生しました」とだけ出し、詳しい内容はログに書きます。

編集(UPDATE)機能はどうする?

今回は実装しませんが、編集機能も考え方は同じです。

  1. 「編集」ボタンでIDを送信し、編集画面に移動する。
  2. そのIDのデータをDBから取得して、入力フォームに表示する(valueに入れる)。
  3. 書き換えて送信されたら、SQLの UPDATE 文で上書き保存する。
UPDATE messages SET comment = '新しい本文' WHERE id = 5

PHPコース卒業!次のステップへ

おめでとうございます!これでHTML、CSS、JavaScript、PHP、そしてデータベースの基礎をすべて学び終えました。

あなたはもう、「画面を作る力」と「データを操る力」の両方を持っています。
最後に、これからプロのエンジニアを目指すためのロードマップを紹介します。

フレームワークを学ぶ(Laravel)

今のPHP開発では、今回のように全て手書き(生のPHP)することは稀です。
セキュリティや便利な機能がセットになった「Laravel(ララベル)」というフレームワークを学ぶのが次のステップです。

バージョン管理を学ぶ(Git)

コードのバックアップや変更履歴を保存する「Git(ギット)」は、チーム開発の必須スキルです。

自分だけのオリジナルアプリを作る

これが一番の近道です。家計簿アプリ、タスク管理、推し活メモ…なんでも構いません。
「作りたいもの」がある時、技術は一番伸びます。

長いコースでしたが、最後までついてきてくれてありがとうございました。
あなたのエンジニアライフが素晴らしいものになりますように!

📝 今日のミニテスト

PHP編最後のテストです!

Q1. データを削除するSQLで、絶対に忘れてはいけないキーワードは?

正解:WHERE
DELETE FROM table だけだと、全データが消えて大惨事になります。

 

Q2. 画面には表示したくないが、データとしてIDなどを送信したい時に使うHTMLタグは?

正解:<input type="hidden" ...>
削除ボタンや編集ボタンの実装で必ず使います。

 

Q3. 既存のデータを書き換える(更新する)SQL命令は?

正解:UPDATE
UPDATE テーブル名 SET カラム = 値 WHERE id = ... という形で使います。

ここまで来ると、あとは「何を作るか」だけです。

私も、業務でRPAのシナリオを書いていました。

だから、この手の詰まり方はよく知っています。
エラーで検索して、出てこなくて、似た事例を読んで、違って、また戻る。
あの時間。

今は、そこをAIに相談します。
ただ、検索窓に単語を入れる感覚で聞くと、AIも的外れなことを言ってきます。
だいたい、そうなる。

「何が起きていて、何をしたいのか」まで渡すと、返ってくるものが変わる。

私はもともと、簡単なものなら自分で作れました。
ただ、そこ止まり。
「これは自分の手には余るな」と思って、やらずに置いていたものが、いくつもあります。

それが、作れるようになりました。
新しく勉強し直したわけじゃない。
AIとの話し方を変えただけ。

まずは、話しかけるところから。

▼AIが怖い人のための、最初のコピペ10選(無料)

タイトルとURLをコピーしました