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

PHP + MySQL UTF-8 編碼亂碼終極解決方案:檔面、資料庫、連線三層統一

     編輯:PHP 綜合知識

UTF-8 亂碼是 PHP 開發者最常遇到的坑。根因在於「檔案編碼、HTML 輸出 Header、PHP 內部處理、MySQL 連線字符集、資料庫/表/欄位字符集」任一環節不一致。本文提供系統性排查清單與標準化配置模板,從源頭杜絕亂碼。

亂碼產生的三大層級

第 1 層:輸出端 (HTTP 響應)
    PHP 檔案編碼 → HTML meta charset → HTTP Header Content-Type

第 2 層:處理端 (PHP 內部)
    字串操作函數 → 正則匹配 → json_encode → 模板引擎

第 3 層:存儲端 (MySQL)
    連線字符集 → 資料庫預設字符集 → 表字符集 → 欄位字符集

標準化配置清單 (逐項核對)

✅ 1. PHP 檔案編碼:UTF-8 無 BOM

  • 編輯器存檔選擇 UTF-8 without BOM (VS Code 右下角、PhpStorm File→File Encoding、Notepad++ 編碼→UTF-8 無 BOM)
  • BOM 會導致 header()、session_start() 提前輸出錯誤
  • 批量轉換工具:find . -name "*.php" -exec iconv -f GBK -t UTF-8 {} -o {}.utf8 \;

✅ 2. HTTP 輸出 Header:最早發送


  • 優先級:header() > <meta charset> > 伺服器預設
  • Nginx/Apache 配置 charset utf-8; 作為兜底

✅ 3. HTML Meta 標籤:雙重保險






✅ 4. MySQL 連線字符集:關鍵一步

$pdo = new PDO(
    "mysql:host=localhost;dbname=test;charset=utf8mb4",
    'user', 'pass',
    [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
// 或 mysqli
$mysqli = new mysqli('localhost', 'user', 'pass', 'test');
$mysqli->set_charset('utf8mb4');  // 必須在查詢前呼叫
// 老式 mysql_* (已棄用)
mysql_query("SET NAMES utf8mb4");
  • 必須用 utf8mb4:支援 Emoji (4 字節),utf8 僅支援 3 字節 (BMP 平面)
  • SET NAMES utf8mb4 等同於同時設定 character_set_client、connection、results

✅ 5. 資料庫/表/欄位字符集:utf8mb4 + 通用排序規則

-- 建庫
CREATE DATABASE `myapp` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 建表
CREATE TABLE `users` (
    `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
    `bio` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 修改現有庫/表/欄位
ALTER DATABASE `myapp` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `users` MODIFY `name` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

排序規則選擇指南

常見亂碼場景診斷表

排序規則特點適用場景
utf8mb4_unicode_ciUCA 標準、多語言支援佳、準確排序通用推薦
utf8mb4_general_ci簡化規則、速度略快、德語/俄語等排序不準舊專案相容、極高效能場景
utf8mb4_bin二進制比較、區分大小寫、可作唯一索引去重大小寫敏感、Base64/Hash 存儲
現象可能原因排查步驟修復
頁面顯示 輸出 Header 非 UTF-8檢查 header()、meta、Nginx charset統一設定 UTF-8 Header
中文變 ???MySQL 連線字符集錯誤檢查 SET NAMES、PDO charset 參數連線加 charset=utf8mb4
存入資料庫變亂碼表/欄位字符集非 utf8mb4SHOW CREATE TABLE 檢查ALTER TABLE CONVERT TO utf8mb4
Emoji 存入截斷/報錯字符集僅 utf8 (3 字節)檢查資料庫/表/欄位/連線全鏈路全鏈路升級 utf8mb4
json_encode 中文成 \uXXXX預設行為非錯誤,前端自動解碼加 JSON_UNESCAPED_UNICODE 參數
substr/strlen 截斷亂碼多字節字元按字節截取用 mb_substr/mb_strlen啟用 mbstring、用 mb_* 函數
正則匹配失效未加 u 修飾符preg_match('/漢字/u', $str)加 u 修飾符、用 mb_ereg

PHP 字串處理最佳實踐

// Laravel .env
DB_CONNECTION=mysql
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci

// config/database.php
'mysql' => [
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    'options' => [
        PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci'
    ]
]

// ThinkPHP config/database.php
'charset' => 'utf8mb4',
// 自動執行 SET NAMES

// CodeIgniter config/database.php
'char_set' => 'utf8mb4',
'dbcollat' => 'utf8mb4_unicode_ci',

遷移舊專案檢查清單

  1. mysqldump --default-character-set=utf8mb4 導出數據
  2. 建立新庫 utf8mb4 導入
  3. 修改所有連線代碼加 charset=utf8mb4
  4. 掃描代碼:grep -r "utf8" --include="*.php" . | grep -v "utf8mb4"
  5. 替換 strlen/substr/strpos 為 mb_strlen/mb_substr/mb_strpos
  6. 正則加 /u 修飾符
  7. 全站瀏覽測試:中文、Emoji、特殊符號、多語言

伺服器層面兜底配置



UTF-8 編碼問題本質是「契約不一致」。建立「全鏈路 utf8mb4」標準,配合代碼規範、靜態掃描、自動化測試,即可從根源消除亂碼困擾。新專案啟動日即落地此標準,舊專案按清單逐步遷移,是專業團隊的基本建設。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved