ตัวอย่าง Project OOP ขนาดเล็ก: สร้างระบบจัดการข้อมูล
มาถึงบทสุดท้ายของซีรีส์การเขียนโปรแกรมเชิงวัตถุ (OOP) ใน PHP สำหรับผู้เริ่มต้นกันแล้วครับ! ในบทนี้ เราจะนำความรู้ทั้งหมดที่เราได้เรียนรู้มาประยุกต์ใช้ในการสร้างโปรเจกต์ OOP ขนาดเล็ก เพื่อให้เห็นภาพรวมและเข้าใจการทำงานของ OOP มากยิ่งขึ้น เราจะสร้างระบบจัดการข้อมูลอย่างง่าย ซึ่งจะช่วยให้เราเห็นการออกแบบ Class, การ Implement Methods และการทดสอบ Code ได้อย่างชัดเจน
โจทย์: ระบบจัดการข้อมูลหนังสือ
เราจะสร้างระบบจัดการข้อมูลหนังสือ (Book Management System) ที่มีความสามารถดังนี้:
- เพิ่มหนังสือใหม่
- แสดงรายการหนังสือทั้งหมด
- ค้นหาหนังสือตามชื่อ
- ลบหนังสือออกจากระบบ
การออกแบบ Class
ขั้นตอนแรกคือการออกแบบ Class ที่จำเป็นสำหรับระบบของเรา ในที่นี้ เราจะใช้ Class หลักๆ 2 Class คือ Book และ BookManager
BookClass: เป็น Class ที่เก็บข้อมูลของหนังสือแต่ละเล่ม จะมี Properties เช่น ชื่อหนังสือ, ผู้แต่ง, ISBNBookManagerClass: เป็น Class ที่จัดการข้อมูลหนังสือทั้งหมด จะมี Methods สำหรับเพิ่ม, ลบ, ค้นหา และแสดงรายการหนังสือ
เหตุผลเชิงออกแบบ (Design Rationale): การแยก Class ออกเป็น Book และ BookManager เป็นไปตามหลักการ Single Responsibility Principle (SRP) ซึ่งบอกว่าแต่ละ Class ควรมีหน้าที่เดียว Book ทำหน้าที่เก็บข้อมูล ส่วน BookManager ทำหน้าที่จัดการข้อมูล ทำให้โค้ดมีความชัดเจนและง่ายต่อการแก้ไข
การ Implement Code
เราจะเริ่ม Implement Code โดยสร้าง Class Book ก่อน:
<?php
class Book {
private $title;
private $author;
private $isbn;
public function __construct(string $title, string $author, string $isbn) {
$this->title = $title;
$this->author = $author;
$this->isbn = $isbn;
}
public function getTitle(): string {
return $this->title;
}
public function getAuthor(): string {
return $this->author;
}
public function getIsbn(): string {
return $this->isbn;
}
public function setTitle(string $title): void {
$this->title = $title;
}
public function setAuthor(string $author): void {
$this->author = $author;
}
public function setIsbn(string $isbn): void {
$this->isbn = $isbn;
}
}
คำอธิบาย Code:
- เรากำหนด Properties
$title,$authorและ$isbnให้เป็นprivateเพื่อป้องกันการเข้าถึงโดยตรงจากภายนอก Class - เราสร้าง Constructor
__construct()เพื่อกำหนดค่าเริ่มต้นให้กับ Properties เมื่อสร้าง Object - เราสร้าง Getter และ Setter Methods เพื่อให้สามารถเข้าถึงและแก้ไข Properties ได้อย่างปลอดภัย (ผ่านการควบคุม)
ต่อไปเราจะสร้าง Class BookManager:
<?php
class BookManager {
private $books = [];
public function addBook(Book $book): void {
$this->books[] = $book;
}
public function removeBook(string $isbn): void {
foreach ($this->books as $key => $book) {
if ($book->getIsbn() === $isbn) {
unset($this->books[$key]);
// Reindex the array to avoid gaps
$this->books = array_values($this->books);
return;
}
}
}
public function findBookByTitle(string $title): ?Book {
foreach ($this->books as $book) {
if (stripos($book->getTitle(), $title) !== false) { // Case-insensitive search
return $book;
}
}
return null;
}
public function getAllBooks(): array {
return $this->books;
}
}
คำอธิบาย Code:
- เรากำหนด Property
$booksเป็น Array เพื่อเก็บ Object ของ ClassBook - Method
addBook()เพิ่ม ObjectBookเข้าไปใน Array$books - Method
removeBook()ลบ ObjectBookออกจาก Array$booksโดยใช้ ISBN ในการระบุ - Method
findBookByTitle()ค้นหา ObjectBookตามชื่อหนังสือ โดยใช้ `stripos` เพื่อทำการค้นหาแบบไม่สนใจตัวพิมพ์เล็ก-ใหญ่ - Method
getAllBooks()คืนค่า Array ของ ObjectBookทั้งหมด
แนวปฏิบัติที่ดี (Best Practices):
- การใช้ Type Hinting (เช่น
Book $bookในaddBook()) ช่วยให้ Code อ่านง่ายและลดข้อผิดพลาด - การคืนค่า
?BookในfindBookByTitle()หมายความว่า Method อาจคืนค่าnullได้ หากไม่พบหนังสือที่ต้องการ - การใช้ `stripos` ใน `findBookByTitle()` ทำให้การค้นหามีความยืดหยุ่นมากขึ้น
การใช้งานระบบ
ตัวอย่างการใช้งานระบบ:
<?php
require_once 'Book.php'; // Assuming Book.php contains the Book class
require_once 'BookManager.php'; // Assuming BookManager.php contains the BookManager class
$book1 = new Book("The Lord of the Rings", "J.R.R. Tolkien", "97806182602");
$book2 = new Book("Pride and Prejudice", "Jane Austen", "9780141439518");
$bookManager = new BookManager();
$bookManager->addBook($book1);
$bookManager->addBook($book2);
$foundBook = $bookManager->findBookByTitle("Lord");
if ($foundBook) {
echo "Found book: " . $foundBook->getTitle() . " by " . $foundBook->getAuthor() . "<br>";
} else {
echo "Book not found.<br>";
}
$allBooks = $bookManager->getAllBooks();
echo "All books:<br>";
foreach ($allBooks as $book) {
echo "- " . $book->getTitle() . " by " . $book->getAuthor() . "<br>";
}
$bookManager->removeBook("9780141439518");
$allBooks = $bookManager->getAllBooks();
echo "<br>All books after removal:<br>";
foreach ($allBooks as $book) {
echo "- " . $book->getTitle() . " by " . $book->getAuthor() . "<br>";
}
คำอธิบาย Code:
- เราสร้าง Object ของ Class
Bookสองเล่ม - เราสร้าง Object ของ Class
BookManager - เราเพิ่ม Object
Bookทั้งสองเล่มเข้าไปในBookManager - เราค้นหาหนังสือตามชื่อ และแสดงผลลัพธ์
- เราแสดงรายการหนังสือทั้งหมด
- เราลบหนังสือเล่มหนึ่งออกจากระบบ
- เราแสดงรายการหนังสือทั้งหมดอีกครั้ง เพื่อตรวจสอบว่าการลบสำเร็จ
การทดสอบ Code
การทดสอบ Code เป็นสิ่งสำคัญเพื่อให้แน่ใจว่า Code ของเราทำงานได้อย่างถูกต้อง เราสามารถใช้ Unit Testing เพื่อทดสอบแต่ละ Method ใน Class ของเรา
ตัวอย่างการใช้ PHPUnit (Framework สำหรับ Unit Testing ใน PHP) เพื่อทดสอบ Class BookManager:
<?php
use PHPUnit\Framework\TestCase;
require_once 'Book.php';
require_once 'BookManager.php';
class BookManagerTest extends TestCase {
public function testAddBook() {
$bookManager = new BookManager();
$book = new Book("Test Book", "Test Author", "1234567890");
$bookManager->addBook($book);
$this->assertCount(1, $bookManager->getAllBooks());
}
public function testRemoveBook() {
$bookManager = new BookManager();
$book = new Book("Test Book", "Test Author", "1234567890");
$bookManager->addBook($book);
$bookManager->removeBook("1234567890");
$this->assertCount(0, $bookManager->getAllBooks());
}
public function testFindBookByTitle() {
$bookManager = new BookManager();
$book = new Book("Test Book", "Test Author", "1234567890");
$bookManager->addBook($book);
$foundBook = $bookManager->findBookByTitle("Test");
$this->assertInstanceOf(Book::class, $foundBook);
$this->assertEquals("Test Book", $foundBook->getTitle());
}
public function testFindBookByTitleNotFound() {
$bookManager = new BookManager();
$foundBook = $bookManager->findBookByTitle("Nonexistent Book");
$this->assertNull($foundBook);
}
}
คำอธิบาย Code:
- เราสร้าง Class
BookManagerTestที่สืบทอดมาจากPHPUnit\Framework\TestCase - เราสร้าง Methods สำหรับทดสอบแต่ละ Method ใน Class
BookManager - เราใช้ Assertion Methods (เช่น
assertCount(),assertInstanceOf(),assertEquals(),assertNull()) เพื่อตรวจสอบผลลัพธ์ของการทำงาน
เหตุผลเชิงออกแบบ (Design Rationale): การใช้ Unit Testing ช่วยให้เรามั่นใจได้ว่า Code ของเราทำงานได้อย่างถูกต้อง และยังช่วยให้เราสามารถ Refactor Code ได้อย่างปลอดภัย เนื่องจากเราสามารถรัน Unit Tests เพื่อตรวจสอบว่าการ Refactor ไม่ทำให้ Code เสียหาย
สรุป
ในบทนี้ เราได้สร้างระบบจัดการข้อมูลหนังสืออย่างง่าย โดยใช้หลักการ OOP ใน PHP เราได้เรียนรู้การออกแบบ Class, การ Implement Methods และการทดสอบ Code ด้วย Unit Testing หวังว่าบทนี้จะช่วยให้คุณเข้าใจการทำงานของ OOP มากยิ่งขึ้น และสามารถนำไปประยุกต์ใช้ในการสร้างโปรเจกต์ที่ใหญ่ขึ้นได้
ขอแสดงความยินดีด้วยครับ! คุณได้จบหลักสูตรการเขียนโปรแกรมเชิงวัตถุ (OOP) ใน PHP สำหรับผู้เริ่มต้นแล้ว หวังว่าความรู้ที่ได้เรียนรู้จะช่วยให้คุณพัฒนาตัวเองไปสู่การเป็นนักพัฒนา PHP ที่เก่งกาจยิ่งขึ้นครับ!