MySQL 字符集流向:
PHP腳本(UTF-8) → client → connection → Server(存儲GBK) → connection → results → PHP顯示(UTF-8)
任一環節不匹配即產生亂碼。Discuz UTF-8 頁面卻用 GBK 存儲的秘密在於顯式設置三層字符集變量。
| 變量 | 含義 | 設置建議 (PHP UTF-8 + DB GBK) |
|---|---|---|
character_set_client | 客戶端發送 SQL 的編碼 | utf8 (PHP 發送 UTF-8 SQL) |
character_set_connection | Server 接收後轉換的目標編碼 | gbk (轉為 GBK 存儲/操作) |
character_set_results | 查詢結果返回給客戶端的編碼 | utf8 (結果轉回 UTF-8 給 PHP) |
// PDO 方式
$pdo = new PDO("mysql:host=localhost;dbname=test", 'user', 'pass');
$pdo->exec("SET character_set_client = utf8");
$pdo->exec("SET character_set_connection = gbk");
$pdo->exec("SET character_set_results = utf8");
// mysqli 方式
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$mysqli->query("SET character_set_client = utf8");
$mysqli->query("SET character_set_connection = gbk");
$mysqli->query("SET character_set_results = utf8");
// 封裝為連接初始化方法
function initCharset($pdo) {
$pdo->exec("SET NAMES utf8"); // 僅當 DB 也為 UTF-8 時使用
// 異構編碼必須分別設置上述三條
}
SET NAMES utf8 不夠?SET NAMES utf8 等同於同時設置上述三變量為 utf8。若資料庫實際存儲為 GBK,會導致「寫入時 UTF-8 → GBK 轉碼錯誤」或「讀出時 GBK → UTF-8 雙重轉碼」。
CREATE DATABASE `test` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
CREATE TABLE `t` (
`name` VARCHAR(20) CHARACTER SET gbk COLLATE gbk_chinese_ci
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
優勢:CHAR(20) 可存 20 個漢字(而非 20/2 或 20/3 字節),LENGTH() 返回字節數,業務邏輯按字符計數更直觀。
<meta charset="utf-8">、HTTP Header Content-Type: text/html; charset=utf-8。iconv 或 mb_convert_encoding 批量轉碼,驗證 HEX(col) 確認存儲正確。