編碼不一致會導致亂碼、資料截斷、資料庫存入錯誤。本文整理 PHP、HTML、資料庫、檔案編碼的統一設定與常見坑點。
<?php
// 必須在任何輸出前呼叫
header('Content-Type: text/html; charset=utf-8'); // 推薦 UTF-8
// 或 GB2312
// header('Content-Type: text/html; charset=gb2312');
?>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- HTML5 簡寫 -->
<meta charset="utf-8">
<?php
// PDO
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', $user, $pass);
$pdo->exec("SET NAMES utf8mb4");
// mysqli
$mysqli->set_charset('utf8mb4');
?>
資料表欄位建議用 utf8mb4_unicode_ci,支援 Emoji 與生僻字。
將 UTF-8 轉 GB2312 時,遇到「—」(EM DASH U+2014)等字元會導致後續字串消失。
<?php
// 錯誤寫法:遇到無法轉換字元會截斷
$gb = iconv('UTF-8', 'GB2312', $utf8);
// 正確寫法:加上 //IGNORE 忽略無法轉換字元,或 //TRANSLIT 嘗試近似替換
$gb = iconv('UTF-8', 'GB2312//IGNORE', $utf8); // 直接刪除問題字元
$gb = iconv('UTF-8', 'GB2312//TRANSLIT', $utf8); // 嘗試轉換為相近字元(如 — → --)
?>
<?php
mb_internal_encoding('UTF-8'); // 內部處理編碼
mb_http_output('UTF-8'); // 輸出編碼
mb_regex_encoding('UTF-8'); // 正則編碼
// 或在 php.ini 設定
// mbstring.internal_encoding = UTF-8
// mbstring.http_output = UTF-8
?>
| 現象 | 可能原因 | 檢查重點 |
|---|---|---|
| 頁面顯示 菱形問號 | 瀏覽器解碼錯誤 | HTTP Header charset、meta charset、檔案實際編碼 |
| 中文變成 ??? 或 亂碼 | 資料庫連線編碼不匹配 | PDO SET NAMES、mysqli set_charset、表欄位 collation |
| iconv 轉碼後字串變短 | 目標編碼無對應字元 | 加 //IGNORE 或 //TRANSLIT |
| JSON 輸出中文變 \uXXXX | json_encode 預設編碼 | 加 JSON_UNESCAPED_UNICODE 參數 |
統一全站 UTF-8(含資料庫 utf8mb4)是現代 PHP 專案的標準配置,能避免 99% 的編碼問題。