# 瀏覽器開發者工具 Network 標籤查看 Response Headers
Content-Type: text/html; charset=gbk ← 關鍵線索!
HTTP 頭優先級高於 HTML meta 標籤,瀏覽器按此編碼解析。
<?php phpinfo(); ?>
# 搜尋 "default_charset"
# 發現:default_charset = "gbk" ← 禍首!
; 修改前
default_charset = "gbk"
; 修改後
default_charset = "UTF-8"
; 或註釋掉,讓頁面自行控制
; default_charset = "UTF-8"
# 重啟 Apache
sudo /etc/init.d/apache2 restart
# 或 XAMPP 控制面板 Restart
header("Content-Type: text/html; charset=UTF-8");(代碼層最高)AddDefaultCharset UTF-8 或 Off<meta charset="UTF-8">| 層級 | 配置位置 | 推薦值 | 備註 |
|---|---|---|---|
| PHP 代碼 | 入口文件頂部 | header("Content-Type: text/html; charset=UTF-8"); | 最可控、最高優先級 |
| PHP 設定 | php.ini | default_charset = "UTF-8" | 全域預設 |
| Apache | httpd.conf / .htaccess | AddDefaultCharset Off | 關閉避免衝突,或設 UTF-8 |
| HTML | <head> | <meta charset="UTF-8"> | 語義標準、SEO 友好 |
| 資料庫 | 連線/建表 | CHARSET=utf8mb4 | utf8mb4 支援 emoji |
| 資料庫連線 | PDO/mysqli | SET NAMES utf8mb4 | 每次連線執行 |
| 檔案編碼 | 編輯器 | UTF-8 無 BOM | 防 BOM 導致 header 輸出失敗 |
header() 失敗。編輯器選「UTF-8 無 BOM」.user.ini(PHP 5.3+)或 ini_set('default_charset', 'UTF-8') 在代碼最頂部.htaccess 加 AddDefaultCharset UTF-8 覆蓋<?php
// encoding_diag.php - 放入專案根目錄訪問
header("Content-Type: text/plain; charset=UTF-8");
echo "=== PHP 編碼診斷 ===\n";
echo "default_charset: " . ini_get('default_charset') . "\n";
echo "mbstring.internal_encoding: " . ini_get('mbstring.internal_encoding') . "\n";
echo "mbstring.http_output: " . ini_get('mbstring.http_output') . "\n";
echo "iconv.internal_encoding: " . ini_get('iconv.internal_encoding') . "\n\n";
echo "=== HTTP 響應頭 ===\n";
echo "Content-Type: " . header_get('Content-Type') . "\n\n";
echo "=== 超全域變數 ===\n";
echo "_SERVER['HTTP_ACCEPT_CHARSET']: " . ($_SERVER['HTTP_ACCEPT_CHARSET'] ?? '未設定') . "\n";
echo "_SERVER['CONTENT_TYPE']: " . ($_SERVER['CONTENT_TYPE'] ?? '未設定') . "\n\n";
echo "=== 測試輸出 ===\n";
echo "中文測試:測試編碼正常\n";
echo "Emoji測試:😀🎉🚀\n";
?>
亂碼本質是**編碼宣告與實際內容不一致**。排查核心:**看 HTTP 響應頭 → 查 php.ini default_charset → 檢查檔案編碼 → 確認資料庫連線編碼**。統一全鏈路 UTF-8(推薦 utf8mb4),在入口文件強制 header() 宣告,是徹底解決之道。