PHP và MySQL – DatabaseDAO Singleton

Dưới đây là cách triển khai mẫu thiết kế Singleton cho DatabaseDAO trong PHP, giúp đảm bảo chỉ có một kết nối cơ sở dữ liệu duy nhất trong toàn bộ ứng dụng.

1. Kết nối Cơ sở Dữ liệu Singleton (DatabaseDAO.php)

Lớp này đảm bảo rằng chỉ có một đối tượng kết nối cơ sở dữ liệu duy nhất được tạo ra.

<?php
class DatabaseDAO {
    private static $instance = null;
    private $conn;
    private $host = "localhost";
    private $dbname = "ten_csd";
    private $username = "ten_nguoi_dung";
    private $password = "mat_khau";

    // Constructor là private để ngăn chặn việc khởi tạo trực tiếp
    private function __construct() {
        $this->connect();
    }

    // Phương thức static để lấy instance duy nhất của lớp
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    // Phương thức để thiết lập kết nối cơ sở dữ liệu
    private function connect() {
        try {
            $this->conn = new PDO("mysql:host=" . $this->host . ";dbname=" . $this->dbname, $this->username, $this->password);
            $this->conn->exec("set names utf8");
            $this->conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch(PDOException $exception) {
            echo "Lỗi kết nối: " . $exception->getMessage();
        }
    }

    // Phương thức để lấy kết nối cơ sở dữ liệu
    public function getConnection() {
        return $this->conn;
    }

    // Ngăn chặn việc nhân bản đối tượng
    private function __clone() {}

    // Ngăn chặn việc unserializing đối tượng
    private function __wakeup() {}
}
?>

2. Sử dụng DatabaseDAO trong các lớp DAO

Khi sử dụng DatabaseDAO Singleton, mỗi lớp DAO sẽ gọi DatabaseDAO::getInstance() để lấy kết nối cơ sở dữ liệu.

Ví dụ với OrderDAO

<?php
require_once 'DatabaseDAO.php';
require_once 'Order.php';

class OrderDAO {
    private $conn;

    public function __construct() {
        $this->conn = DatabaseDAO::getInstance()->getConnection();
    }

    public function getAllOrders() {
        $query = "SELECT id, user_id, order_date, status FROM orders";
        $stmt = $this->conn->prepare($query);
        $stmt->execute();

        $orders = [];

        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $order = new Order();
            $order->setId($row['id']);
            $order->setUserId($row['user_id']);
            $order->setOrderDate($row['order_date']);
            $order->setStatus($row['status']);

            $orders[] = $order;
        }

        return $orders;
    }

    // Các phương thức khác để thực hiện CRUD (tạo, cập nhật, xóa) ở đây
}
?>

3. Lợi ích của việc sử dụng mẫu Singleton cho Kết nối Cơ sở Dữ liệu

  1. Quản lý Tài nguyên: Chỉ có một instance của kết nối cơ sở dữ liệu được tạo ra, giúp giảm thiểu tài nguyên sử dụng và cải thiện quản lý tài nguyên.
  2. Tính nhất quán: Đảm bảo rằng cùng một kết nối cơ sở dữ liệu được sử dụng xuyên suốt ứng dụng, duy trì tính nhất quán.
  3. Hiệu suất: Giảm nhu cầu tạo nhiều kết nối, điều này có thể tốn tài nguyên và làm chậm ứng dụng.

4. Truy cập Kết nối Cơ sở Dữ liệu

Khi cần tương tác với cơ sở dữ liệu, hãy sử dụng DatabaseDAO::getInstance()->getConnection() để lấy đối tượng kết nối duy nhất. Điều này đảm bảo rằng tất cả các DAO và các lớp khác đều tương tác với cùng một kết nối.

Bằng cách sử dụng mẫu Singleton, bạn đảm bảo rằng ứng dụng của bạn quản lý kết nối cơ sở dữ liệu một cách hiệu quả và tránh các vấn đề thường gặp liên quan đến việc tạo nhiều kết nối.