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

PHP 連接 MySQL 中文亂碼終極解決方案:SET NAMES 原理與最佳實踐

     編輯:PHP 綜合知識

現象還原

遷移服務器後,MySQL 從 4.x 升級到 5.0,PHP 讀取中文全變問號 ??? 或亂碼 锟斤拷。根因:客戶端/連接字符集未顯式指定,MySQL 5.0+ 預設 latin1,導致編碼錯位。

一行代碼解決


原理:SET NAMES 'utf8' 等價於執行三條語句:

SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
  • character_set_client:客戶端發送 SQL 的編碼
  • character_set_connection:連接層轉換目標編碼
  • character_set_results:結果集返回給客戶端的編碼

完整最佳實踐(PDO 版)

 PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES => false, // 使用真實預處理
];
try {
    $pdo = new PDO($dsn, $user, $pass, $options);
    // 已自動執行 SET NAMES utf8mb4
} catch (PDOException $e) {
    die("連接失敗: " . $e->getMessage());
}

編碼鏈路完整檢查清單

常見誤區

  1. 以為 SET NAMES 只需執行一次:長連接(如 Swoole、Workerman)需每次獲取連接時執行。
  2. 使用 utf8 而非 utf8mb4:MySQL utf8 偽 utf8(最多 3 字節),無法存 Emoji、生僻字,必須用 utf8mb4。
  3. 只設置數據庫/表編碼,忽略連接編碼:連接編碼不匹配是亂碼首因。
  4. PHP 文件保存為 ANSI/GBK:導致字符串字面量編碼與連接編碼不一致。

遷移歷史數據修正腳本

setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->query("SHOW TABLES");
while ($table = $stmt->fetchColumn()) {
    $cols = $pdo->query("SHOW COLUMNS FROM `$table`")->fetchAll(PDO::FETCH_ASSOC);
    foreach ($cols as $col) {
        if (in_array($col['Type'], ['varchar', 'text', 'char', 'tinytext', 'mediumtext', 'longtext'])) {
            // 1. 先轉回二進制,再按 GBK 解讀,寫入 utf8mb4 列
            $pdo->exec("ALTER TABLE `$table` MODIFY `{$col['Field']}` VARBINARY(255)");
            $pdo->exec("ALTER TABLE `$table` MODIFY `{$col['Field']}` VARCHAR(255) CHARACTER SET utf8mb4");
            // 實際需分批 UPDATE CONVERT(CAST(`col` AS BINARY) USING gbk) ... 視數據量而定
        }
    }
}

結語

中文亂碼本質是編碼鏈路斷點。核心動作:數據庫/表/列用 utf8mb4,連接用 SET NAMES utf8mb4(或 DSN charset),PHP 文件存 UTF-8,HTML 輸出聲明 charset。PDO + DSN charset 是現代 PHP 最省心、最不易出錯的方案。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
環節檢查項正確配置
數據庫CREATE DATABASE charsetDEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
表CREATE TABLE charsetDEFAULT CHARSET=utf8mb4
列VARCHAR/TEXT charsetCHARSET=utf8mb4(或繼承表)
連接PHP 連接字符集SET NAMES utf8mb4 / DSN charset=utf8mb4
PHP 文件源碼文件編碼UTF-8 without BOM
HTML 輸出Content-Type charsetheader('Content-Type: text/html; charset=utf-8') / <meta charset="utf-8">
瀏覽器頁面編碼識別自動檢測或強制 UTF-8