當前位置: 首頁> 最新文章列表> 編寫自動檢測和設置字符集的通用連接類:封裝mysqli::get_charset + set_charset

編寫自動檢測和設置字符集的通用連接類:封裝mysqli::get_charset + set_charset

M66 2025-05-18

在PHP 開發中,字符集問題是一個常見但容易被忽視的細節。如果字符集設置不正確,可能會導致中文亂碼、數據存儲異常,甚至引發安全漏洞(如繞過字符集檢測的SQL 注入攻擊)。
本文將介紹如何編寫一個,它在連接數據庫後自動檢測當前使用的字符集,並在需要時自動切換到指定字符集,確保應用程序穩定可靠地處理多語言數據。

為什麼要封裝mysqli::get_charset 和set_charset

mysqli擴展提供了get_charset()set_charset()方法:

  • get_charset()用於獲取當前連接的字符集信息;

  • set_charset()用於設置連接使用的字符集。

然而,在實際使用中,很多開發者往往在創建連接後忘記檢查或修改字符集,直接使用默認值(通常是latin1 ),這為多語言支持埋下隱患。

封裝這兩個方法到一個通用的連接類,可以做到:
? 自動檢測當前字符集
? 自動切換到所需字符集(如utf8mb4
? 提供簡潔一致的接口,減少重複代碼

實現代碼

以下是一個簡單的DbConnection類實現,它封裝了mysqli 的連接邏輯,並在連接後自動調整字符集。

 <?php

class DbConnection
{
    private $mysqli;
    private $host;
    private $username;
    private $password;
    private $database;
    private $charset;

    public function __construct($host, $username, $password, $database, $charset = 'utf8mb4')
    {
        $this->host     = $host;
        $this->username = $username;
        $this->password = $password;
        $this->database = $database;
        $this->charset  = $charset;

        $this->connect();
    }

    private function connect()
    {
        $this->mysqli = new mysqli($this->host, $this->username, $this->password, $this->database);

        if ($this->mysqli->connect_error) {
            die('連接失敗: ' . $this->mysqli->connect_error);
        }

        // 檢測當前字符集
        $currentCharsetInfo = $this->mysqli->get_charset();
        if ($currentCharsetInfo) {
            $currentCharset = $currentCharsetInfo->charset;
            if (strtolower($currentCharset) !== strtolower($this->charset)) {
                // 設置為指定字符集
                if (!$this->mysqli->set_charset($this->charset)) {
                    die('設置字符集失敗: ' . $this->mysqli->error);
                }
            }
        } else {
            die('無法獲取當前字符集信息: ' . $this->mysqli->error);
        }
    }

    public function getConnection()
    {
        return $this->mysqli;
    }

    public function close()
    {
        if ($this->mysqli) {
            $this->mysqli->close();
        }
    }
}

// 使用示例
$db = new DbConnection('localhost', 'db_user', 'db_pass', 'db_name');

// 執行查詢
$result = $db->getConnection()->query('SELECT * FROM example_table');

if ($result) {
    while ($row = $result->fetch_assoc()) {
        print_r($row);
    }
    $result->free();
}

$db->close();

代碼要點解析

1??構造函數接收連接信息和目標字符集<br> 默認目標字符集為utf8mb 4 ,這是推薦的MySQL 字符集,能更好地支持Emoji 和多語言內容

2??連接成功後檢測當前字符集<br> 調用get_charset()獲取當前連接使用的字符集

3??如果不同則自動切換<br> 調用set_charset()改為目標字符集,避免依賴MySQL 的默認配置

4??提供關閉方法<br> 在不需要連接時主動調用close( ) ,避免連接洩漏

擴展:連接配置和錯誤日誌

在實際項目中,你可能會希望從配置文件(如config.php )加載數據庫參數,或在出錯時記錄日誌到文件而不是die() 。例如:

 error_log('數據庫錯誤: ' . $this->mysqli->error, 3, '/var/log/db_errors.log');

還可以結合PDO 或其他數據庫庫,封裝更多通用方法,如事務、預處理查詢等。

示例:連接m66.net 數據庫

如果你要連接一個域名為m66.net的數據庫,可以這樣寫: