四層編碼必須一致
| 層級 | 設定方式 | 範例值 | 優先序 |
| 1. HTTP 回應標頭 | PHP header() | Content-Type: text/html; charset=UTF-8 | 最高(瀏覽器最優先遵守) |
| 2. HTML meta 標籤 | <meta charset="UTF-8"> | UTF-8 | 次之(無 HTTP 標頭時生效) |
| 3. PHP/HTML 檔案儲存編碼 | 編輯器「另存新檔」選 UTF-8 無 BOM | UTF-8 | 原始碼層級,影響字串字面常數 |
| 4. 資料庫連線/表/欄位 | SET NAMES utf8mb4、CHARSET=utf8mb4 | utf8mb4 | 資料存取層,防止存入亂碼 |
PHP 統一設定範本(放入 common.php / bootstrap)
<?php
// 1. HTTP 標頭(必須在任何輸出前)
header('Content-Type: text/html; charset=UTF-8');
// 2. 內部編碼(影響 mbstring、正則等)
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
mb_regex_encoding('UTF-8');
// 3. 資料庫連線編碼 (PDO)
$pdo = new PDO($dsn, $user, $pass, [
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci',
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
// 4. 預設時區
date_default_timezone_set('Asia/Taipei');
?>
常見亂碼場景診斷
| 現象 | 可能原因 | 排查步驟 |
| 頁面顯示 | 瀏覽器以錯誤編碼解碼 | 檢查 HTTP 標頭、meta、檔案編碼三者一致 |
| 資料庫讀出 ??? | 連線編碼錯誤 | 執行 SET NAMES utf8mb4、確認欄位 CHARSET |
| 表單送入亂碼 | 頁面編碼非 UTF-8 | 表單頁面強制 UTF-8、accept-charset="UTF-8" |
| JSON 輸出中文變 \uXXXX | 正常行為 | 前端 JSON.parse 自動還原,或 JSON_UNESCAPED_UNICODE |
大小寫規範
- **HTTP 標頭、HTML meta、PHP header()、ini_set()**:統一大寫
UTF-8
- **MySQL 唯一例外**:
SET NAMES utf8mb4(無連字號),CHARSET=utf8mb4
- 其他場合(XML 宣告、CSS @charset、JS 檔案編碼)皆用
UTF-8
BOM 陷阱
**UTF-8 with BOM** 會在檔案開頭插入 EF BB BF,導致 header() 失效(已有輸出)、**XML 解析錯誤**、**Composer 自動載入失敗**。**務必用 UTF-8 無 BOM** 儲存。