🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

[PHP สำหรับผู้เริ่มต้น] การพัฒนาเว็บแอปที่ใช้งานได้จริง! สร้างกระดานข่าวสั้นๆ ด้วยการเชื่อมต่อฐานข้อมูล

ในบทความที่ผ่านมา เราได้เรียนรู้ไวยากรณ์พื้นฐานของ PHP และวิธีดึงข้อมูลจากฐานข้อมูลมาแสดงผลแล้ว แต่ความสนุกที่แท้จริงของการพัฒนาเว็บแอปพลิเคชันนั้น อยู่ที่การที่ผู้ใช้สามารถ "เพิ่ม" หรือ "ลบ" ข้อมูลได้ ซึ่งเป็นการโต้ตอบแบบสองทาง "การจัดการข้อมูลโดยผู้ใช้" นี้เองที่เป็นหัวใจของบริการเว็บทุกประเภท

ในบทความนี้ เราจะรวบรวมความรู้ทั้งหมดที่ผ่านมาเพื่อพัฒนาเว็บแอปพลิเคชันที่ทำงานร่วมกับฐานข้อมูลอย่างเต็มรูปแบบ นั่นคือ กระดานข่าวสำหรับข้อความสั้นๆ กระดานข่าวนี้จะมี 3 ฟังก์ชันพื้นฐานของเว็บแอป ได้แก่ การโพสต์ข้อความ (Create), การแสดงรายการ (Read) และการลบ (Delete) แม้โค้ดจะยาวไปหน่อย แต่ถ้าคุณคัดลอกไฟล์นี้ไปวางและรันบนเซิร์ฟเวอร์ของคุณ คุณก็จะได้ "เว็บแอปพลิเคชันที่ใช้งานได้จริง" เป็นของตัวเอง มาสัมผัสกับความรู้สึกของการประสบความสำเร็จอันยิ่งใหญ่ในการเขียนโปรแกรมกันเถอะครับ!

สำหรับการเตรียมตัวเพื่อรัน PHP (สภาพแวดล้อมการพัฒนา) หากคุณยังไม่ได้ติดตั้ง XAMPP โปรดอ้างอิงจาก [PHP สำหรับผู้เริ่มต้น] คู่มือฉบับสมบูรณ์เกี่ยวกับการดาวน์โหลดและติดตั้ง XAMPP! หลังจากติดตั้งแล้ว เพียงแค่วางไฟล์ PHP ของคุณในโฟลเดอร์ที่กำหนด (เช่น `htdocs`) ก็พร้อมใช้งานแล้วครับ!

1. CRUD: การออกแบบพื้นฐานของเว็บแอปพลิเคชัน

เว็บแอปพลิเคชันที่เราใช้กันอยู่ทุกวัน เช่น โซเชียลมีเดีย, บล็อก, หรือเว็บไซต์อีคอมเมิร์ซ โดยพื้นฐานแล้วประกอบด้วยการจัดการข้อมูล 4 รูปแบบ ซึ่งเรียกโดยใช้ตัวอักษรย่อว่า CRUD (ครัด)

ในครั้งนี้ เราจะมาลองสร้างฟังก์ชัน 3 อย่างคือ C, R, D โดยไม่รวมการแก้ไข (Update) เพื่อเป็นก้าวแรกสู่การพัฒนาเว็บแอปพลิเคชันกันครับ

2. ภาคปฏิบัติ! มาพัฒนากระดานข่าวสั้นๆ กันเถอะ

งั้นเรามาเริ่มสร้างกันเลยครับ เราจะสร้างฟังก์ชันการโพสต์, การแสดงผล, และการลบทั้งหมดไว้ในไฟล์ PHP ไฟล์เดียวกัน

ขั้นตอน A: การเตรียมฐานข้อมูลและตาราง

ก่อนอื่น เราต้องสร้างตาราง `memos` สำหรับเก็บข้อความในฐานข้อมูลก่อน โดยใช้เครื่องมือจัดการฐานข้อมูลอย่าง phpMyAdmin แล้วรันคำสั่ง SQL ต่อไปนี้ครับ

CREATE TABLE memos (
  id INT AUTO_INCREMENT PRIMARY KEY,
  content VARCHAR(255) NOT NULL,
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- ลองใส่ข้อมูลตัวอย่างลงไปสักหน่อย
INSERT INTO memos (content) VALUES
('เริ่มเรียน PHP'),
('คิดเมนูอาหารเย็นวันนี้'),
('ทำรายการของที่จะซื้อสุดสัปดาห์นี้');

ขั้นตอน B: ไฟล์ PHP ที่รวมทุกฟังก์ชัน

จากนี้ไปคือของจริงครับ ให้บันทึกโค้ดต่อไปนี้เป็นชื่อไฟล์เช่น `memo.php` ซึ่งในไฟล์เดียวนี้จะมีทั้งข้อมูลการเชื่อมต่อฐานข้อมูล, ตรรกะการเพิ่มข้อมูล, ตรรกะการลบ, และตรรกะการแสดงผลทั้งหมดรวมอยู่ด้วยกัน

<!DOCTYPE html>
<html lang="th">
<head>
    <meta charset="UTF-8">
    <title>กระดานข่าวสั้นๆ</title>
    <style>
        body { font-family: sans-serif; padding: 20px; max-width: 700px; margin: auto; background-color: #f9f9f9; }
        h1, h2 { color: #333; border-bottom: 2px solid #007bff; padding-bottom: 10px; }
        .memo-form { background: #fff; padding: 20px; border-radius: 8px; margin-bottom: 30px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        textarea { width: 100%; height: 60px; padding: 10px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; margin-bottom: 10px; }
        button { padding: 10px 20px; border: none; background-color: #28a745; color: white; border-radius: 4px; cursor: pointer; }
        button:hover { background-color: #218838; }
        .memo-list { list-style: none; padding: 0; }
        .memo-item { background: #fff; padding: 15px; border-left: 5px solid #007bff; margin-bottom: 15px; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
        .memo-content { flex-grow: 1; }
        .memo-date { font-size: 0.8em; color: #888; display: block; margin-top: 5px; }
        .delete-btn { background-color: #dc3545; }
        .delete-btn:hover { background-color: #c82333; }
        .error-message { color: red; font-weight: bold; }
    </style>
</head>
<body>
    <h1>กระดานข่าวสั้นๆ</h1>

    <?php
    // --- ข้อมูลการเชื่อมต่อฐานข้อมูล ---
    $db_host = 'localhost';
    $db_name = 'your_database_name';
    $db_user = 'your_username';
    $db_pass = 'your_password';

    try {
        $pdo = new PDO("mysql:host={$db_host};dbname={$db_name};charset=utf8", $db_user, $db_pass);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        // --- การประมวลผลข้อมูล (กรณีมี request แบบ POST) ---
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (isset($_POST['action']) && $_POST['action'] === 'add') {
                // 【Create】 การประมวลผลเพิ่มข้อความ
                if (!empty($_POST['content'])) {
                    $stmt = $pdo->prepare("INSERT INTO memos (content) VALUES (:content)");
                    $stmt->execute([':content' => $_POST['content']]);
                }
            } elseif (isset($_POST['action']) && $_POST['action'] === 'delete') {
                // 【Delete】 การประมวลผลลบข้อความ
                if (isset($_POST['id'])) {
                    $stmt = $pdo->prepare("DELETE FROM memos WHERE id = :id");
                    $stmt->execute([':id' => $_POST['id']]);
                }
            }
            // หลังจากประมวลผลแล้ว ให้ redirect มาที่ตัวเองเพื่อป้องกันการโพสต์ซ้ำ
            header('Location: ' . $_SERVER['SCRIPT_NAME']);
            exit;
        }

        // --- การแสดงผลข้อมูล (กรณีมี request แบบ GET) ---
        // 【Read】 ดึงรายการข้อความ
        $stmt = $pdo->prepare("SELECT * FROM memos ORDER BY created_at DESC");
        $stmt->execute();
        $memos = $stmt->fetchAll(PDO::FETCH_ASSOC);

    } catch (PDOException $e) {
        echo '<div class="error-message">ข้อผิดพลาดฐานข้อมูล: ' . htmlspecialchars($e->getMessage()) . '</div>';
        die(); // หยุดการทำงานเมื่อเกิดข้อผิดพลาด
    }
    ?>

    <!-- ฟอร์มโพสต์ข้อความ -->
    <section class="memo-form">
        <h2>โพสต์ข้อความใหม่</h2>
        <form action="" method="POST">
            <input type="hidden" name="action" value="add">
            <textarea name="content" required></textarea>
            <button type="submit">โพสต์</button>
        </form>
    </section>

    <!-- แสดงรายการข้อความ -->
    <section>
        <h2>รายการข้อความ</h2>
        <ul class="memo-list">
            <?php if ($memos): ?>
                <?php foreach ($memos as $memo): ?>
                    <li class="memo-item">
                        <div class="memo-content">
                            <?php echo htmlspecialchars($memo['content']); ?>
                            <span class="memo-date">(<?php echo $memo['created_at']; ?>)</span>
                        </div>
                        <form action="" method="POST" style="display:inline;">
                            <input type="hidden" name="action" value="delete">
                            <input type="hidden" name="id" value="<?php echo $memo['id']; ?>">
                            <button type="submit" class="delete-btn">ลบ</button>
                        </form>
                    </li>
                <?php endforeach; ?>
            <?php else: ?>
                <li>ยังไม่มีโพสต์</li>
            <?php endif; ?>
        </ul>
    </section>

</body>
</html>

สำคัญ: อย่าลืมแก้ไขข้อมูลการเชื่อมต่อฐานข้อมูลให้ตรงกับสภาพแวดล้อมของคุณก่อนรันโค้ดนี้นะครับ

เป็นอย่างไรบ้างครับ? คุณน่าจะสามารถยืนยันการทำงานทั้งหมดได้แล้ว คือเมื่อโพสต์ข้อความจากฟอร์ม ข้อความนั้นจะถูกเพิ่มเข้าไปในรายการแบบเรียลไทม์ และเมื่อกดปุ่มลบ ข้อความนั้นก็จะหายไป นี่คือการทำงานพื้นฐานของ CRUD (ในที่นี้คือ CRD) ในการพัฒนาเว็บแอปพลิเคชันครับ

3. คำอธิบายโค้ดและประเด็นสำคัญ

ในโค้ดไฟล์เดียวนี้ มีเทคนิคสำคัญๆ อยู่หลายอย่างครับ

กลไกการประมวลผลทุกอย่างในไฟล์เดียว

แอปนี้จัดการทั้งการส่งข้อมูล (POST) และการแสดงผลหน้าเว็บ (GET) ในไฟล์เดียวกัน โดยใช้ `if ($_SERVER['REQUEST_METHOD'] === 'POST')` เพื่อรวบรวมการประมวลผล "เมื่อมีการส่งฟอร์ม" ครับ ทั้งการเพิ่มและการลบจะถูกรับมาเป็น request แบบ POST และเมื่อประมวลผลเสร็จแล้วก็จะ redirect กลับมาที่ตัวเอง เทคนิคนี้เรียกว่า **Post/Redirect/Get (PRG) Pattern** ซึ่งมีผลช่วยป้องกัน "การโพสต์ซ้ำ" ที่เกิดจากการกดปุ่มรีเฟรชของเบราว์เซอร์แล้วข้อมูลเดิมถูกส่งไปซ้ำๆ

การใช้ input type="hidden"

ทั้งฟอร์มโพสต์และปุ่มลบต่างก็ส่งข้อมูลไปยังไฟล์เดียวกันด้วยวิธี POST เพื่อที่จะแยกแยะได้ว่าต้องการให้ประมวลผลอะไร เราจึงใช้ `<input type="hidden">` ครับ

<!-- ฝั่งฟอร์มโพสต์ -->
<input type="hidden" name="action" value="add">

<!-- ฝั่งฟอร์มลบ -->
<input type="hidden" name="action" value="delete">
<input type="hidden" name="id" value="<?php echo $memo['id']; ?>">

ด้วยวิธีนี้ การส่งข้อมูลที่ซ่อนไว้ซึ่งไม่แสดงบนหน้าจอ เช่น "`action` (เป็นการกระทำอะไร)" หรือ "`id` (จะกระทำกับข้อความไหน)" ไปพร้อมกัน จะทำให้ฝั่ง PHP สามารถดูข้อมูลที่ได้รับแล้วทำการประมวลผลที่เหมาะสม (เพิ่ม หรือ ลบ) ได้นั่นเอง

4. สรุปและขั้นตอนต่อไป

お疲れ様でした!今回は、データベースと連携し、データの作成(Create)、読み込み(Read)、削除(Delete)の機能を持つ、動的なWebアプリケーション「一言メモ掲示板」を作成しました。自分の書いたコードがブラウザ上で実際に「アプリ」として動く体験は、大きな自信に繋がったのではないでしょうか。

このCRUDの考え方は、あらゆるWebアプリケーションの基礎となります。ここからさらに、

คุณสามารถขยายฟังก์ชันการทำงานในรูปแบบเหล่านี้ต่อไปได้ ลองใช้กระดานข่าวนี้เป็นพื้นฐานแล้วท้าทายตัวเองในการพัฒนาแอปพลิเคชันที่เป็นออริจินัลของคุณดูนะครับ!