ThinkPHP 3.x 預設使用 UTF-8 編碼,而早期中文版 SQL Server (MSSQL) 預設儲存資料為 GB2312(或 CP936)編碼。當 PHP 以 UTF-8 讀取 GB2312 資料時,若未做轉碼,中文會顯示為亂碼(如「æ°ä¸」或「???」)。
在資料從資料庫查出後、回傳給模型/控制器前,統一將結果集從 GB2312 轉為 UTF-8。最簡單的切入點是修改核心類別 ThinkPHP/Lib/Core/Db.class.php 中的 select() 方法。
在 Db.class.php 類別末尾(或適當位置)加入:
/**
* 將查詢結果集從 GB2312 轉為 UTF-8
* @param array $result 原始查詢結果(二維陣列)
* @return array 轉碼後的結果集
*/
protected function iconv2utf8($result) {
if (empty($result)) return $result;
$rowKeys = array_keys($result);
$colKeys = array_keys($result[$rowKeys[0]]);
$converted = [];
foreach ($rowKeys as $rowKey) {
foreach ($colKeys as $colKey) {
$val = $result[$rowKey][$colKey];
$converted[$rowKey][$colKey] = is_string($val) ? iconv('GB2312', 'UTF-8//IGNORE', $val) : $val;
}
}
return $converted;
}
說明:使用 //IGNORE 避免遇到無法轉換的字元時中斷;僅對字串型欄位轉碼,保留數值、NULL 等型別。
找到 public function select(),在 $result = $this->query($sql); 之後、回傳前插入:
$result = $this->iconv2utf8($result);
完整片段示意:
public function select($sql = '') {
// ... 原有邏輯 ...
$result = $this->query($sql);
// 新增:編碼轉換
$result = $this->iconv2utf8($result);
return $result;
}
ThinkPHP 3.x 年代久遠,若專案允許,強烈建議升級至 ThinkPHP 5.1+ 或 6.x,並改用 Microsoft 官方 sqlsrv / PDO_SQLSRV 驅動,連線 DSN 指定 CharacterSet=UTF-8,即可從根源解決編碼問題,無需修改核心碼。
INSERT INTO test (name) VALUES (N'中文測試')。M('test')->select()。Latin1 或其他,請將 iconv 的 from 參數對應調整。透過在 Db 核心類別統一轉碼,可快速解決 ThinkPHP 3.x 讀取 MSSQL 中文亂碼問題。長遠來說,建議規劃框架升級與驅動現代化,徹底消除編碼困擾。