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