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

PHP 操作 MySQL 基礎類封裝:從 mysql_* 到 PDO 的現代化重構

     編輯:PHP 相關知識

原文使用已棄用的 mysql_* 函數(PHP 7.0 移除),存在 SQL 注入風險且無法使用預處理語句。本文在保留原有功能邏輯的基礎上,重構為基於 PDO 的現代化數據庫操作類,支持預處理、事務、異常處理,並修復原代碼中的安全漏洞。

警告:mysql_connect、mysql_query 等函數自 PHP 5.5 棄用,PHP 7.0 完全移除。所有新項目必須使用 PDO 或 mysqli。

現代化 PDO 封裝類

<?php
/**
 * 簡易 PDO 數據庫操作類
 * 支持預處理、事務、錯誤異常模式
 */
class Database
{
    private \PDO $pdo;
    private string $tablePrefix = '';

    public function __construct(array $config)
    {
        $dsn = "mysql:host={$config['host']};dbname={$config['dbname']};charset={$config['charset'] ?? 'utf8mb4'}";
        $options = [
            \PDO::ATTR_ERRMODE            => \PDO::ERRMODE_EXCEPTION, // 拋出異常
            \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC,       // 關聯陣列
            \PDO::ATTR_EMULATE_PREPARES   => false,                   // 真實預處理
            \PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES {$config['charset'] ?? 'utf8mb4'}",
        ];

        try {
            $this->pdo = new \PDO($dsn, $config['user'], $config['pass'], $options);
        } catch (\PDOException $e) {
            // 生產環境應記錄日誌而非直接輸出
            throw new \RuntimeException('數據庫連接失敗: ' . $e->getMessage());
        }
    }

    // 設置表前綴
    public function setTablePrefix(string $prefix): self
    {
        $this->tablePrefix = $prefix;
        return $this;
    }

    // 通用查詢:返回所有行
    public function fetchAll(string $sql, array $params = []): array
    {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchAll();
    }

    // 通用查詢:返回單行
    public function fetchOne(string $sql, array $params = []): ?array
    {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetch() ?: null;
    }

    // 通用查詢:返回單值
    public function fetchValue(string $sql, array $params = [])
    {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->fetchColumn();
    }

    // 執行增刪改:返回影響行數
    public function execute(string $sql, array $params = []): int
    {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt->rowCount();
    }

    // 插入並返回自增 ID
    public function insert(string $table, array $data): int
    {
        $fields = implode(', ', array_keys($data));
        $placeholders = ':' . implode(', :', array_keys($data));
        $sql = "INSERT INTO `{$this->tablePrefix}{$table}` ($fields) VALUES ($placeholders)";
        $this->execute($sql, $data);
        return (int)$this->pdo->lastInsertId();
    }

    // 更新
    public function update(string $table, array $data, string $where, array $whereParams = []): int
    {
        $set = implode(', ', array_map(fn($k) => "`$k` = :$k", array_keys($data)));
        $sql = "UPDATE `{$this->tablePrefix}{$table}` SET $set WHERE $where";
        return $this->execute($sql, array_merge($data, $whereParams));
    }

    // 刪除
    public function delete(string $table, string $where, array $params = []): int
    {
        $sql = "DELETE FROM `{$this->tablePrefix}{$table}` WHERE $where";
        return $this->execute($sql, $params);
    }

    // 事務支持
    public function beginTransaction(): void { $this->pdo->beginTransaction(); }
    public function commit(): void { $this->pdo->commit(); }
    public function rollBack(): void { $this->pdo->rollBack(); }

    // 獲取底層 PDO 實例(高級用法)
    public function getPdo(): \PDO { return $this->pdo; }
}
?>

使用示例

<?php
require_once 'Database.php';

$config = [
    'host'   => 'localhost',
    'user'   => 'root',
    'pass'   => '123456',
    'dbname' => 'products',
    'charset'=> 'utf8mb4',
];

$db = new Database($config);

// 查詢分類列表
$categories = $db->fetchAll("SELECT * FROM `category`");
foreach ($categories as $row) {
    echo "ID: {$row['id']}, Name: {$row['name']}<br>";
}

// 安全插入(預處理防注入)
$newId = $db->insert('category', ['name' => '新分類']);
echo "插入成功,ID: $newId<br>";

// 安全更新
$affected = $db->update('category', ['name' => '更新名稱'], 'id = :id', ['id' => $newId]);
echo "更新行數: $affected<br>";

// 安全刪除
$deleted = $db->delete('category', 'id = :id', ['id' => $newId]);
echo "刪除行數: $deleted<br>";
?>

核心改進對比

維度原 mysql_* 代碼重構 PDO 類
SQL 注入防護無(字符串拼接)預處理參數綁定
字符集utf8(不支持 Emoji)utf8mb4(完整 Unicode)
錯誤處理手動判斷返回值異常模式,統一 try-catch
事務支持無內建 beginTransaction/commit/rollBack
代碼復用分散的過程式代碼封裝 CRUD、鏈式調用
PHP 版本兼容≤ 5.6≥ 5.1(推薦 7.4+)

最佳實踐提醒

  • 生產環境配置文件應與代碼分離(如 .env + vlucas/phpdotenv)。
  • 避免在循環中執行 SQL,改用批量插入 INSERT ... VALUES (...), (...) 或事務包裹。
  • 大數據量查詢使用 fetchAll 會佔用大量內存,改用 while ($row = $stmt->fetch()) 游標式讀取。
  • 考慮引入成熟 ORM(Eloquent、Doctrine、Cycle ORM)進一步提升開發效率與代碼質量。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved