メインコンテンツへ移動

เนื้อหาภาษาไทย / タイ語のコンテンツ

システムガイド 内容確認済み

การใช้ PDO กับ Pagination

บทความนี้อธิบายวิธีการใช้งาน PDO ใน PHP เพื่อสร้างระบบ Pagination สำหรับเว็บไซต์ที่มีข้อมูลจำนวนมาก โดยครอบคลุมตั้งแต่การคำนวณจำนวนหน้าทั้งหมด, การดึงข้อมูลเฉพา...

การใช้ PDO กับ Pagination

ในบทเรียนนี้ เราจะมาเรียนรู้วิธีการใช้งาน PDO (PHP Data Objects) เพื่อจัดการกับการแบ่งหน้าข้อมูล หรือ Pagination ซึ่งเป็นฟังก์ชันที่สำคัญมากสำหรับเว็บไซต์ที่มีข้อมูลจำนวนมาก Pagination ช่วยให้ผู้ใช้สามารถนำทางไปยังข้อมูลที่ต้องการได้อย่างง่ายดาย โดยไม่ต้องโหลดข้อมูลทั้งหมดในครั้งเดียว

เราจะครอบคลุมหัวข้อดังนี้:

  • การคำนวณจำนวนหน้าทั้งหมด
  • การดึงข้อมูลตามหน้าที่ผู้ใช้เลือก
  • การสร้างลิงก์สำหรับนำทางไปยังหน้าต่างๆ

การคำนวณจำนวนหน้าทั้งหมด

ขั้นตอนแรกในการทำ Pagination คือการคำนวณจำนวนหน้าทั้งหมดที่เราต้องการแสดงผล จำนวนหน้านี้ขึ้นอยู่กับจำนวนข้อมูลทั้งหมดในฐานข้อมูล และจำนวนข้อมูลที่เราต้องการแสดงผลต่อหนึ่งหน้า

สมมติว่าเรามีตารางชื่อ `products` ที่เก็บข้อมูลสินค้า และเราต้องการแสดงสินค้า 10 รายการต่อหนึ่งหน้า โค้ดต่อไปนี้จะแสดงวิธีการคำนวณจำนวนหน้าทั้งหมด:

<?php
// กำหนดจำนวนรายการต่อหน้า
$itemsPerPage = 10;

// เชื่อมต่อฐานข้อมูล
$dsn = 'mysql:host=localhost;dbname=mydatabase;charset=utf8mb4';
$user = 'username';
$pass = 'password';

try {
    $pdo = new PDO($dsn, $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    exit;
}

// นับจำนวนรายการทั้งหมดในตาราง
$stmt = $pdo->query("SELECT COUNT(*) FROM products");
$totalItems = $stmt->fetchColumn();

// คำนวณจำนวนหน้าทั้งหมด
$totalPages = ceil($totalItems / $itemsPerPage);

echo "จำนวนหน้าทั้งหมด: " . $totalPages;
?>

คำอธิบายโค้ด:

  • `$itemsPerPage = 10;` กำหนดจำนวนรายการที่เราต้องการแสดงผลต่อหนึ่งหน้า
  • ส่วนของการเชื่อมต่อฐานข้อมูล (PDO) เหมือนกับที่เราเคยทำในบทเรียนก่อนๆ
  • `$stmt = $pdo->query("SELECT COUNT(*) FROM products");` ทำการ Query เพื่อนับจำนวนรายการทั้งหมดในตาราง `products`
  • `$totalItems = $stmt->fetchColumn();` ดึงผลลัพธ์จากการ Query (จำนวนรายการทั้งหมด)
  • `$totalPages = ceil($totalItems / $itemsPerPage);` คำนวณจำนวนหน้าทั้งหมด โดยใช้ฟังก์ชัน `ceil()` เพื่อปัดเศษขึ้นเสมอ

ข้อผิดพลาดที่พบบ่อย:

  • ลืมปัดเศษ: หากไม่ใช้ `ceil()` อาจทำให้จำนวนหน้าไม่ถูกต้อง โดยเฉพาะเมื่อจำนวนรายการทั้งหมดหารด้วยจำนวนรายการต่อหน้าไม่ลงตัว
  • การเชื่อมต่อฐานข้อมูลผิดพลาด: ตรวจสอบให้แน่ใจว่าข้อมูลการเชื่อมต่อฐานข้อมูลถูกต้อง

การดึงข้อมูลตามหน้า

เมื่อเราทราบจำนวนหน้าทั้งหมดแล้ว ขั้นตอนต่อไปคือการดึงข้อมูลตามหน้าที่ผู้ใช้เลือก เราจะใช้คำสั่ง `LIMIT` และ `OFFSET` ใน SQL เพื่อกำหนดช่วงของข้อมูลที่เราต้องการดึง

`LIMIT` คือจำนวนรายการที่เราต้องการดึง ในกรณีของเราคือ `$itemsPerPage`

`OFFSET` คือตำแหน่งเริ่มต้นของรายการที่เราต้องการดึง หากเราต้องการดึงข้อมูลในหน้าแรก `OFFSET` จะเป็น 0 หากเป็นหน้าสอง `OFFSET` จะเป็น `$itemsPerPage` และอื่นๆ

โค้ดต่อไปนี้จะแสดงวิธีการดึงข้อมูลตามหน้าที่ผู้ใช้เลือก:

<?php
// กำหนดจำนวนรายการต่อหน้า
$itemsPerPage = 10;

// รับหมายเลขหน้าจาก Query String (เช่น ?page=2)
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;

// ตรวจสอบว่าหมายเลขหน้าถูกต้อง
if ($page < 1) {
    $page = 1;
}

// คำนวณ OFFSET
$offset = ($page - 1) * $itemsPerPage;

// เชื่อมต่อฐานข้อมูล (เหมือนเดิม)
$dsn = 'mysql:host=localhost;dbname=mydatabase;charset=utf8mb4';
$user = 'username';
$pass = 'password';

try {
    $pdo = new PDO($dsn, $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    exit;
}


// ดึงข้อมูลจากฐานข้อมูล
$stmt = $pdo->prepare("SELECT * FROM products LIMIT :limit OFFSET :offset");
$stmt->bindParam(':limit', $itemsPerPage, PDO::PARAM_INT);
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();

$products = $stmt->fetchAll(PDO::FETCH_ASSOC);

// แสดงข้อมูล
echo "<ul>";
foreach ($products as $product) {
    echo "<li>" . $product['name'] . "</li>";
}
echo "</ul>";
?>

คำอธิบายโค้ด:

  • `$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;` รับหมายเลขหน้าจาก Query String หากไม่มี Query String จะกำหนดให้เป็นหน้าแรก (1)
  • `if ($page < 1) { $page = 1; }` ตรวจสอบว่าหมายเลขหน้าถูกต้อง หากน้อยกว่า 1 จะกำหนดให้เป็น 1
  • `$offset = ($page - 1) * $itemsPerPage;` คำนวณค่า `OFFSET` โดยนำหมายเลขหน้าลบด้วย 1 แล้วคูณด้วยจำนวนรายการต่อหน้า
  • `$stmt = $pdo->prepare("SELECT * FROM products LIMIT :limit OFFSET :offset");` เตรียม Prepared Statement โดยใช้ Placeholders `:limit` และ `:offset`
  • `$stmt->bindParam(':limit', $itemsPerPage, PDO::PARAM_INT);` และ `$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);` ผูกค่าให้กับ Placeholders โดยระบุชนิดข้อมูลเป็น `PDO::PARAM_INT` เพื่อความปลอดภัย
  • `$stmt->execute();` ทำการ Execute Query
  • `$products = $stmt->fetchAll(PDO::FETCH_ASSOC);` ดึงข้อมูลทั้งหมดในรูปแบบ Associative Array
  • ส่วนของการแสดงผลข้อมูล (loop) เป็นเพียงตัวอย่าง คุณสามารถปรับแต่งให้แสดงข้อมูลในรูปแบบที่ต้องการได้

ข้อผิดพลาดที่พบบ่อย:

  • ไม่ได้ตรวจสอบค่า `$_GET['page']`: หากไม่ได้ตรวจสอบค่า `$_GET['page']` อาจทำให้เกิดปัญหาเมื่อผู้ใช้ใส่ค่าที่ไม่ถูกต้อง เช่น ตัวอักษร หรือค่าที่น้อยกว่า 1
  • ไม่ได้ใช้ Prepared Statements: การใช้ Prepared Statements ช่วยป้องกัน SQL Injection
  • ลืมกำหนดชนิดข้อมูล: การกำหนดชนิดข้อมูล (เช่น `PDO::PARAM_INT`) ช่วยเพิ่มความปลอดภัย

การสร้างลิงก์สำหรับ Pagination

ขั้นตอนสุดท้ายคือการสร้างลิงก์สำหรับนำทางไปยังหน้าต่างๆ เราจะสร้างลิงก์ไปยังหน้าก่อนหน้า, หน้าถัดไป และหน้าอื่นๆ ในช่วงที่กำหนด

โค้ดต่อไปนี้จะแสดงวิธีการสร้างลิงก์สำหรับ Pagination:

<?php
// (ส่วนของการเชื่อมต่อฐานข้อมูลและการคำนวณ $totalPages เหมือนเดิม)

// กำหนดจำนวนรายการต่อหน้า
$itemsPerPage = 10;

// รับหมายเลขหน้าจาก Query String (เช่น ?page=2)
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;

// ตรวจสอบว่าหมายเลขหน้าถูกต้อง
if ($page < 1) {
    $page = 1;
}

// คำนวณ OFFSET
$offset = ($page - 1) * $itemsPerPage;

// เชื่อมต่อฐานข้อมูล (เหมือนเดิม)
$dsn = 'mysql:host=localhost;dbname=mydatabase;charset=utf8mb4';
$user = 'username';
$pass = 'password';

try {
    $pdo = new PDO($dsn, $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    exit;
}

// นับจำนวนรายการทั้งหมดในตาราง
$stmt = $pdo->query("SELECT COUNT(*) FROM products");
$totalItems = $stmt->fetchColumn();

// คำนวณจำนวนหน้าทั้งหมด
$totalPages = ceil($totalItems / $itemsPerPage);

// ดึงข้อมูลจากฐานข้อมูล
$stmt = $pdo->prepare("SELECT * FROM products LIMIT :limit OFFSET :offset");
$stmt->bindParam(':limit', $itemsPerPage, PDO::PARAM_INT);
$stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();

$products = $stmt->fetchAll(PDO::FETCH_ASSOC);

// แสดงข้อมูล
echo "<ul>";
foreach ($products as $product) {
    echo "<li>" . $product['name'] . "</li>";
}
echo "</ul>";


// สร้างลิงก์ Pagination
echo "<div class='pagination'>";

// ลิงก์หน้าก่อนหน้า
if ($page > 1) {
    echo "<a href='?page=" . ($page - 1) . "'>ก่อนหน้า</a> ";
}

// ลิงก์หน้าต่างๆ
for ($i = 1; $i <= $totalPages; $i++) {
    if ($i == $page) {
        echo "<span>" . $i . "</span> "; // หน้าปัจจุบัน
    } else {
        echo "<a href='?page=" . $i . "'>" . $i . "</a> ";
    }
}

// ลิงก์หน้าถัดไป
if ($page < $totalPages) {
    echo "<a href='?page=" . ($page + 1) . "'>ถัดไป</a>";
}

echo "</div>";
?>

คำอธิบายโค้ด:

  • ส่วนของการเชื่อมต่อฐานข้อมูล, การคำนวณ `$totalPages`, และการดึงข้อมูลเหมือนเดิม
  • `echo "<div class='pagination'>";` สร้าง `div` เพื่อใส่ลิงก์ Pagination (คุณสามารถใส่ CSS เพื่อตกแต่งได้)
  • ส่วนของการสร้างลิงก์:
    • `if ($page > 1) { ... }` สร้างลิงก์ "ก่อนหน้า" หากไม่ใช่หน้าแรก
    • `for ($i = 1; $i <= $totalPages; $i++) { ... }` สร้างลิงก์ไปยังหน้าต่างๆ โดยวนลูปตั้งแต่หน้า 1 ถึงหน้าสุดท้าย หากเป็นหน้าปัจจุบัน จะแสดงเป็น `span` แทนที่จะเป็นลิงก์
    • `if ($page < $totalPages) { ... }` สร้างลิงก์ "ถัดไป" หากไม่ใช่หน้าสุดท้าย

ข้อผิดพลาดที่พบบ่อย:

  • ลืมตรวจสอบเงื่อนไข: การลืมตรวจสอบเงื่อนไข (เช่น `$page > 1` หรือ `$page < $totalPages`) อาจทำให้เกิดลิงก์ "ก่อนหน้า" หรือ "ถัดไป" ที่ไม่ถูกต้อง
  • ไม่ได้ใส่ CSS: ลิงก์ Pagination ที่ไม่ได้ใส่ CSS อาจดูไม่สวยงาม

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

Office.in.th Custom Service

この構成をもとにシステムを開発・カスタマイズしたいですか?

Office.in.th は、エンタープライズ Web アプリケーション、API 連携、官民の業務管理システムの設計・開発を承り、長期的なサポートも提供します。

ソフトウェア開発サービスを見る