Full-Stack PHP 8 ตอนที่ 10: เชื่อมต่อ MySQL กับ PHP ด้วย PDO

บทความนี้เป็นส่วนหนึ่งของซีรีส์ Full-Stack PHP 8 + Bootstrap 5 + MySQL — สร้างเว็บไซต์แบบ Full Stack ตั้งแต่พื้นฐานจนใช้งานได้จริง พร้อมสร้างและเผยแพร่เว็บไซต์ Portfolio ของตนเอง (เรียบเรียงจากคู่มืออบรมของ Wutthiphon Tassana — Wirabyte CO., LTD.) — ตอนที่ 10/10

บทนี้คือการนำทุกอย่างมาต่อกัน ให้หน้าเว็บ PHP ของเราคุยกับฐานข้อมูล MySQL ได้จริง เครื่องมือที่ใช้คือ PDO (PHP Data Objects) ซึ่งเป็นตัวกลางเชื่อมต่อฐานข้อมูลที่ติดมากับ PHP อยู่แล้ว จุดเด่นคือรองรับ Prepared Statement วิธีส่งคำสั่ง SQL ที่ปลอดภัย ช่วยป้องกันการโจมตีแบบ SQL Injection

การเขียน PHP PDO เชื่อมต่อฐานข้อมูล

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

ตัวอย่าง ไฟล์ db.php (ส่วนเชื่อมต่อ)

<?php
// ================== ค่าเชื่อมต่อฐานข้อมูล ==================
$config = array();
$config['db_user'] = "root"; // Database User
$config['db_pass'] = ""; // Database Password
$config['db_host'] = "localhost"; // Database Host
$config['db_db'] = "portfolio_db"; // Database Name
// ================== เชื่อมต่อฐานข้อมูลด้วย PDO ==================
try {
$pdo = new PDO("mysql:host=" . $config['db_host'] . ";dbname=" . $config['db_db'] . ";charset=utf8mb4", $config['db_user'], $config['db_pass']);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
} catch (PDOException $e) {
die("เชื่อมต่อฐานข้อมูลไม่สำเร็จ : " . $e->getMessage());
}
  • charset=utf8mb4 ทำให้เก็บภาษาไทยได้ถูกต้องไม่เป็นตัวประหลาด
  • ERRMODE_EXCEPTION สั่งให้แจ้ง Error ทันทีเมื่อคำสั่ง SQL ผิด จะได้รู้ว่าต้องแก้ตรงไหน
  • FETCH_ASSOC ทำให้ผลลัพธ์เป็น array ที่เรียกใช้ด้วยชื่อคอลัมน์ เช่น $row[‘title’]

การทำ Helper Function สำหรับ Query ข้อมูล

เพื่อไม่ต้องเขียนคำสั่ง prepare และ execute ยาว ๆ ทุกครั้ง เราสร้างฟังก์ชันชื่อ query() ไว้ท้ายไฟล์ db.php แล้วเรียกใช้ซ้ำได้ทั้งเว็บ จุดสำคัญคือใน SQL ให้ใส่เครื่องหมาย ? แทนตำแหน่งของค่าที่มาจากผู้ใช้ แล้วส่งค่าจริงผ่าน array ในตัวแปรที่สอง

ตัวอย่าง ไฟล์ db.php (ส่วน Helper Function)

// ===== Helper Function สำหรับ Query ข้อมูล =====
function query($sql, $array = array()) {
global $pdo;
$q = $pdo->prepare($sql);
$q->execute($array);
return $q;
}

ลำดับการทำงานของ query() ตั้งแต่หน้าเว็บ PHP จนถึง MySQL

การ Query ข้อมูลแบบ Single Row

ถ้าต้องการข้อมูลเพียงแถวเดียว เช่น เปิดดูผลงานตาม id ที่ส่งมากับ URL ให้ต่อท้าย query() ด้วย ->fetch() จะได้ array ของแถวนั้นมาใช้งานทันที

ตัวอย่าง

<?php
include_once dirname(__FILE__) . '/db.php';
// รับ id จาก URL เช่น project.php?id=5
$project = query("SELECT * FROM projects WHERE id=?", array($_GET['id']))->fetch();
echo $project['title'];
?>

การ Query ข้อมูลแบบ Multiple Rows

ถ้าผลลัพธ์มีหลายแถว เช่น ผลงานทั้งหมด ให้นำ query() ไปวนใน foreach ได้เลย โปรแกรมจะหยิบข้อมูลมาให้ทีละแถวจนครบทุกแถว

ตัวอย่าง

<?php foreach (query("SELECT * FROM projects ORDER BY id DESC") as $project) { ?>
<h5><?php echo $project['title']; ?></h5>
<?php } ?>

อีกวิธีหนึ่งคือต่อท้ายด้วย ->fetchAll() เพื่อเก็บผลลัพธ์ทุกแถวมาไว้ในตัวแปรเดียวเป็น array ก่อน เหมาะกับกรณีที่ต้องนำข้อมูลชุดเดียวกันไปใช้หลายจุด หรืออยากนับจำนวนแถวด้วย count()

ตัวอย่าง การใช้ fetchAll()

<?php
// เก็บผลลัพธ์ทุกแถวเป็น array ไว้ในตัวแปร $projects
$projects = query("SELECT * FROM projects ORDER BY id DESC")->fetchAll();
echo "มีผลงานทั้งหมด " . count($projects) . " ชิ้น";
?>
<?php foreach ($projects as $project) { ?>
<h5><?php echo $project['title']; ?></h5>
<?php } ?>

การนำข้อมูลที่ Query ได้มาแสดงผล

ก่อนแสดงข้อมูลที่มาจากผู้ใช้หรือจากฐานข้อมูล ให้ครอบด้วยฟังก์ชัน htmlspecialchars() เสมอ เพื่อแปลงอักขระพิเศษอย่าง < > ให้กลายเป็นข้อความธรรมดา ป้องกันผู้ไม่หวังดีพิมพ์โค้ดแปลกปลอมมาฝังในหน้าเว็บของเรา (การโจมตีแบบ XSS)

ตัวอย่าง

<?php foreach (query("SELECT * FROM messages ORDER BY id DESC") as $msg) { ?>
<b><?php echo htmlspecialchars($msg['name']); ?></b>
<p><?php echo htmlspecialchars($msg['message']); ?></p>
<?php } ?>

🧪 Workshop 7: Query ผลงานและรางวัล กับ สมุดเยี่ยมมาแสดงผล , เพิ่มการ Insert หน้าสมุดเยี่ยมให้เสร็จสมบูรณ์เพื่อให้เพื่อน ๆ ส่งข้อความทิ้งไว้ได้

จากเดิมให้เขียน PHP สำหรับเชื่อมต่อฐานข้อมูล และสร้าง Helper Function สำหรับช่วย Query จากนั้นทำการเขียนหน้าผลงานและรางวัล กับหน้าสมุดเยี่ยมให้ดึงข้อมูลจากฐานข้อมูลมาแสดงผลได้ และในหน้าสมุดเยี่ยมต้องสามารถ Insert ข้อมูลได้จริงเพื่อให้เพื่อน ๆ สามารถมา Comment ได้

วิธีทำ

  • สร้าง Folder ชื่อ db ภายใต้ Folder assets เดิม แล้วสร้างไฟล์ db.php ข้างใน
  • นำ code ที่ได้เรียนรู้ก่อนหน้าไปใส่และทำการเชื่อมต่อฐานข้อมูล
  • เรียกใช้ไฟล์โดยการ include_once ที่ header.php
  • ในหน้า ผลงานและรางวัล กับหน้า สมุดเยี่ยม ทดสอบแสดงผลข้อมูล
  • ที่หน้า สมุดเยี่ยม ทำให้ บันทึกข้อความได้จริงโดยสร้างไฟล์ action.php
  • แก้ไขฟอร์มให้ส่งข้อมูลไปยัง action.php ในรูปแบบ method post
  • เขียน PHP รับ -> เพิ่มเข้าฐานข้อมูล -> ส่งผู้ใช้กลับไปยังหน้า สมุดเยี่ยม
  • ปรับรูปแบบการแสดงผลให้สวยงาม เช่นเปลี่ยนมาแสดงผลด้วย Card หรือ ตาราง (Exclusive) ทั้งหน้าผลงานและรางวัล กับ หน้าสมุดเยี่ยม
  • ทำให้เพิ่มผลงานและรางวัลได้ (INSERT) (Exclusive)
  • ทำให้แก้ไขผลงานและรางวัลได้ (UPDATE) (Exclusive)
  • ทำให้ลบผลงานและรางวัลได้ (DELETE) (Exclusive)
  • ที่หน้ารางวัลให้ JOIN เพื่อนำข้อมูลชื่อประเภทผลงานมาแสดงผลด้วย (LEFT JOIN) (Exclusive) ตามตัวอย่างคำสั่งนี้
SELECT projects.*, categories.name FROM projects LEFT JOIN categories ON categories.id = category_id;
Wutthiphon Tassana
Wutthiphon Tassana