PlusMagi's Blog By Pitt Phunsanit API,architecture,Backend,computer science,PHP PHP: Architectural Patterns (กลุ่มสถาปัตยกรรมเว็บ)

PHP: Architectural Patterns (กลุ่มสถาปัตยกรรมเว็บ)


1. แนวคิดและหลักการทำงานของ Architectural Patterns (กลุ่มสถาปัตยกรรมเว็บ)

ในฐานะนักพัฒนา PHP ระดับสูง การเข้าใจถึง Architectural Patterns ไม่ใช่แค่เรื่องของการเลือกใช้ Framework แต่คือการทำความเข้าใจ “โครงสร้าง” ของระบบทั้งหมด วัตถุประสงค์หลักของสถาปัตยกรรมเหล่านี้คือการบรรลุ Separation of Concerns (SoC) ซึ่งหมายถึงการแยกส่วนความรับผิดชอบออกจากกันอย่างชัดเจน

เมื่อเรานำรูปแบบสถาปัตยกรรม เช่น Model-View-Controller (MVC), Service Layer, หรือ Repository Pattern มาใช้ จะช่วยให้โค้ดของเรามีคุณสมบัติดังนี้:

  • Maintainability: เมื่อต้องการแก้ไขฟังก์ชันใด ฟังก์ชันนั้นจะถูกจำกัดอยู่ในชั้น (Layer) ที่รับผิดชอบเท่านั้น ไม่ส่งผลกระทบต่อส่วนอื่นของระบบ
  • Testability: แต่ละ Component สามารถถูกทดสอบได้อย่างอิสระ (Unit Testing) โดยไม่ต้องรันระบบทั้งหมด
  • Scalability: ระบบสามารถขยายขนาดได้ง่าย เพราะการเพิ่มฟีเจอร์ใหม่ทำได้โดยการเพิ่ม Layer ใหม่ ไม่ใช่การยัดโค้ดเข้าไปในไฟล์เดิมๆ

2. ไวยากรณ์ (Syntax) และตัวอย่างโค้ดการใช้งาน

เราจะใช้รูปแบบ MVC เป็นตัวอย่างหลัก เนื่องจากเป็น Pattern ที่พบได้บ่อยที่สุดใน PHP Frameworks ส่วนใหญ่ การทำความเข้าใจว่า Model, View, และ Controller มีหน้าที่อะไร จะช่วยให้คุณจัดโครงสร้างโค้ดได้อย่างถูกต้อง

  • Model (M): จัดการกับ Business Logic และ Data Interaction (เช่น การติดต่อฐานข้อมูล)
  • View (V): รับผิดชอบในการแสดงผล (Presentation Layer) มักจะเป็น HTML/Template Engine
  • Controller (C): ทำหน้าที่เป็นตัวกลาง (Mediator) รับ Input จากผู้ใช้และเรียก Model เพื่อประมวลผล ก่อนจะส่งข้อมูลไปให้ View แสดงผล
<pre class="wp-block-syntaxhighlighter-code"><?php
// ------------------------------------
// 1. Model Layer (Business Logic & Data)
// ------------------------------------
class UserModel {
    private $db;

    public function __construct($databaseConnection) {
        $this->db = $databaseConnection; // Dependency Injection
    }

    /**
     * ดึงข้อมูลผู้ใช้จากฐานข้อมูล
     */
    public function findUserById(int $userId): ?array {
        // ในความเป็นจริงควรใช้ Prepared Statements เสมอ
        $stmt = $this->db->prepare("SELECT * FROM users WHERE id = :id");
        $stmt->bindParam(':id', $userId);
        $stmt->execute();
        return $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
    }
}

// ------------------------------------
// 2. Controller Layer (Handling Request)
// ------------------------------------
class UserController {
    private UserModel $userModel;

    public function __construct(UserModel $model) {
        $this->userModel = $model; // รับ Model เข้ามาผ่าน Constructor
    }

    /**
     * จัดการ Logic เมื่อมีการร้องขอหน้าโปรไฟล์ผู้ใช้
     */
    public function showProfile(int $userId): void {
        // 1. เรียก Model เพื่อดึงข้อมูล (Business Logic)
        $userData = $this->userModel->findUserById($userId);

        if (!$userData) {
            http_response_code(404);
            echo "Error: User not found.";
            return;
        }

        // 2. ส่งข้อมูลที่ได้ไปให้ View แสดงผล (Separation of Concerns)
        $viewData = [
            'user' => $userData,
            'title' => 'User Profile'
        ];
        View::render('profile', $viewData); // สมมติว่ามีคลาส View
    }
}

// ------------------------------------
// 3. View Layer (Presentation) - จำลองการทำงาน
// ------------------------------------
class View {
    public static function render(string $template, array $data): void {
        // ในความเป็นจริงคือการ include ไฟล์ template และส่งตัวแปรเข้าไป
        echo "<h1>" . ($data['title'] ?? 'Page') . "</h1>";
        echo "<p>Welcome back, " . htmlspecialchars($data['user']['name']) . "</p>";
    }
}

// --- การเรียกใช้งาน (Simulation) ---
$db = new class { // Mock DB connection
    public function prepare(string $sql): object { return new stdClass(); }
    public function bindParam(string $param, mixed $value): void {}
    public function execute(): bool { return true; }
    public function fetch(int $mode): ?array { return ['id' => 1, 'name' => 'John Doe', 'email' => '[email protected]']; }
};

$userModel = new UserModel($db);
$controller = new UserController($userModel);

// เริ่มต้นการทำงานของระบบ
$controller->showProfile(1);
?></pre>

3. Best Practices และคำแนะนำด้าน Performance / Security

  • Dependency Injection (DI): ควรใช้ DI Container เพื่อจัดการการสร้าง Object แทนการใช้ `new` โดยตรง การทำเช่นนี้จะทำให้โค้ดของเราเป็น Loose Coupling และง่ายต่อการ Mock ใน Unit Test
  • Security (SQL Injection): ห้ามรัน Query ที่สร้างจาก String Concatenation โดยเด็ดขาด! ต้องใช้ Prepared Statements เสมอ ไม่ว่าจะเป็น PDO หรือ ORM ใดๆ ก็ตาม
  • Performance (Caching): ใช้ Caching Layer เช่น Redis หรือ Memcached สำหรับข้อมูลที่ถูกเรียกบ่อยแต่ไม่เปลี่ยนแปลงบ่อย (เช่น ข้อมูลการตั้งค่าระบบ, รายชื่อหมวดหมู่) เพื่อลดภาระของ Database

โดยสรุปแล้ว การเลือกใช้ Architectural Pattern ที่เหมาะสม ไม่ได้หมายถึงการเพิ่มความซับซ้อน แต่คือการสร้าง “ขอบเขต” (Boundaries) ให้กับโค้ดของคุณอย่างชัดเจน ทำให้ระบบ PHP ของคุณมีความยืดหยุ่น ทนทานต่อการเปลี่ยนแปลง และพร้อมสำหรับการเติบโตในระยะยาว

Exit mobile version