首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 資料庫操作輔助類 (DBHelper) 封裝範例 (mysqli 版)

     編輯:PHP 相關知識

PHP 資料庫操作輔助類 (DBHelper) 封裝範例

將重複的資料庫連線、查詢、關閉邏輯封裝為輔助類別,能減少樣板碼並統一錯誤處理。本文提供一個基於 MySQLi (物件導向) 的 DBHelper 類別範例,支援預處理語句、交易控制與常用查詢方法。注意: 原文使用已移除的 mysql_* 函式,此處已現代化重寫。

DBHelper 類別完整程式碼

<?php
class DBHelper {
    private $mysqli;
    private $host, $user, $pass, $dbname, $charset;

    public function __construct(array $config) {
        $this->host = $config['host'] ?? 'localhost';
        $this->user = $config['user'] ?? 'root';
        $this->pass = $config['pass'] ?? '';
        $this->dbname = $config['dbname'] ?? '';
        $this->charset = $config['charset'] ?? 'utf8mb4';
    }

    // 延遲連線:首次用到時才連線
    private function connect() {
        if ($this->mysqli instanceof mysqli) return;
        
        $this->mysqli = new mysqli($this->host, $this->user, $this->pass, $this->dbname);
        if ($this->mysqli->connect_errno) {
            throw new Exception("資料庫連線失敗: " . $this->mysqli->connect_error);
        }
        $this->mysqli->set_charset($this->charset);
    }

    // 執行預處理語句 (INSERT, UPDATE, DELETE, REPLACE)
    // 回傳影響行數 (int) 或 false
    public function execute(string $sql, array $params = [], array $types = []): int|false {
        $this->connect();
        $stmt = $this->mysqli->prepare($sql);
        if (!$stmt) throw new Exception("Prepare 失敗: " . $this->mysqli->error . " [SQL: $sql]");
        
        if ($params) {
            $typeStr = $types ? implode('', $types) : str_repeat('s', count($params)); // 預設皆為字串
            $stmt->bind_param($typeStr, ...$params);
        }
        
        $ok = $stmt->execute();
        $affected = $stmt->affected_rows;
        $stmt->close();
        return $ok ? $affected : false;
    }

    // 查詢單筆資料 (關聯陣列)
    public function queryOne(string $sql, array $params = [], array $types = []): array|false {
        $this->connect();
        $stmt = $this->mysqli->prepare($sql);
        if (!$stmt) throw new Exception("Prepare 失敗: " . $this->mysqli->error);
        if ($params) {
            $typeStr = $types ? implode('', $types) : str_repeat('s', count($params));
            $stmt->bind_param($typeStr, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        $row = $result->fetch_assoc();
        $stmt->close();
        return $row ?: false;
    }

    // 查詢多筆資料 (關聯陣列陣列)
    public function queryAll(string $sql, array $params = [], array $types = []): array {
        $this->connect();
        $stmt = $this->mysqli->prepare($sql);
        if (!$stmt) throw new Exception("Prepare 失敗: " . $this->mysqli->error);
        if ($params) {
            $typeStr = $types ? implode('', $types) : str_repeat('s', count($params));
            $stmt->bind_param($typeStr, ...$params);
        }
        $stmt->execute();
        $result = $stmt->get_result();
        $rows = $result->fetch_all(MYSQLI_ASSOC);
        $stmt->close();
        return $rows;
    }

    // 取得最後插入的 AUTO_INCREMENT ID
    public function lastInsertId(): int {
        $this->connect();
        return $this->mysqli->insert_id;
    }

    // 交易控制
    public function beginTransaction(): bool { $this->connect(); return $this->mysqli->begin_transaction(); }
    public function commit(): bool { $this->connect(); return $this->mysqli->commit(); }
    public function rollback(): bool { $this->connect(); return $this->mysqli->rollback(); }

    // 關閉連線
    public function close(): void {
        if ($this->mysqli instanceof mysqli) {
            $this->mysqli->close();
            $this->mysqli = null;
        }
    }

    // 解構子自動關閉
    public function __destruct() { $this->close(); }
}
?>

使用範例

<?php
require_once 'DBHelper.php';

// 1. 設定連線參數 (建議從環境變數或獨立 config.php 讀取)
$config = [
    'host' => 'localhost',
    'user' => 'root',
    'pass' => '123456',
    'dbname' => 'mymessage',
    'charset' => 'utf8mb4',
];

$db = new DBHelper($config);

try {
    // 2. 新增資料 (預處理防注入)
    $sql = "INSERT INTO messages (title, content, created_at) VALUES (?, ?, NOW())";
    $affected = $db->execute($sql, ['測試標題', '測試內容']);
    if ($affected) {
        $newId = $db->lastInsertId();
        echo "新增成功,ID: $newId";
    }

    // 3. 查詢單筆
    $msg = $db->queryOne("SELECT * FROM messages WHERE id = ?", [$newId]);
    var_dump($msg);

    // 4. 查詢列表
    $list = $db->queryAll("SELECT id, title FROM messages ORDER BY id DESC LIMIT 10");
    foreach ($list as $row) {
        echo "{$row['id']}: {$row['title']}
"; } // 5. 交易範例 $db->beginTransaction(); try { $db->execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1"); $db->execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2"); $db->commit(); echo "轉帳成功"; } catch (Exception $e) { $db->rollback(); echo "轉帳失敗: " . $e->getMessage(); } } catch (Exception $e) { error_log("DB Error: " . $e->getMessage()); echo "系統錯誤,請稍後再試"; } finally { $db->close(); } ?>

設計重點說明

進階建議:改用 PDO

MySQLi 僅支援 MySQL。若專案未來可能切換資料庫 (PostgreSQL, SQLite, SQL Server),建議直接使用 PDO,API 幾乎相同但支援多種驅動程式,且具備 fetchClass、fetchObject 等更豐富的資料映射功能。

此 DBHelper 為輕量級封裝,適合中小型專案或學習參考。大型專案建議採用成熟的 ORM (Eloquent, Doctrine) 或 Database Abstraction Layer (DBAL)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性說明
延遲連線建構子不連線,首次查詢/執行才連線,減少不必要開銷
強制預處理所有公開方法皆使用 prepare() + bind_param(),從根源杜絕 SQL 注入
型別推導未指定型別時預設 s (字串),MySQLi 會自動轉型,簡化呼叫
例外處理錯誤拋出 Exception,呼叫端統一 try-catch,避免 die() 破壞流程
資源管理每個 Statement 用完即 close();類別解構子自動關閉連線