瀏覽器判斷網頁編碼的優先順序:
Content-Type: text/html; charset=utf-8(最高優先級)AddDefaultCharset:預設為所有回應加上 Header(次高)<meta http-equiv="Content-Type" content="text/html; charset=utf-8">(最低,僅在前兩者缺失時生效)<?php
// 必須在任何輸出前呼叫
header('Content-Type: text/html; charset=utf-8');
// 或 JSON API
header('Content-Type: application/json; charset=utf-8');
?>
優點:程式碼控制,不依賴伺服器設定,部署到任何環境皆生效。
# /etc/httpd/conf/httpd.conf 或 /etc/apache2/apache2.conf
AddDefaultCharset UTF-8
# 或註解關閉,交由 PHP/Meta 控制
# AddDefaultCharset Off
修改後 systemctl reload httpd。缺點:虛擬主機通常無權修改;若 PHP 已送 Header,Apache 設定會被覆蓋。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- HTML5 簡寫 -->
<meta charset="utf-8">
</head>
缺點:屬於 HTML 內容,瀏覽器需先下載部分內容才能解析,若前面有非 ASCII 字元易產生誤判。
MySQL 連線、資料庫、資料表、欄位編碼必須一致:
-- 建庫建表
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE TABLE users (...) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- PHP PDO 連線指定字元集
$pdo = new PDO('mysql:host=localhost;dbname=mydb;charset=utf8mb4', $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
注意: utf8mb4 支援完整 Unicode(含 Emoji),utf8 僅支援 BMP 平面。
| 現象 | 原因 | 解法 |
|---|---|---|
| 中文顯示 | 瀏覽器以 ISO-8859-1 解碼 UTF-8 資料 | 確認 PHP header() 輸出正確 charset |
| 中文顯示 鍗┿兂 | UTF-8 資料被當作 GBK/Big5 解碼 | 統一所有層為 UTF-8,資料庫連線指定 charset |
| 資料庫存入亂碼 | 連線字元集與資料表不一致 | PDO DSN 加 charset=utf8mb4,或 SET NAMES utf8mb4 |
| curl 獲取遠端頁面亂碼 | 遠端編碼非 UTF-8 | iconv('GBK', 'UTF-8', $content) 或 mb_convert_encoding |
header('Content-Type: text/html; charset=utf-8');。<meta charset="utf-8"> 放在 <head> 最前面。AddDefaultCharset Off 避免干擾(若有權限)。accept-charset="utf-8"。編碼問題本質是「生產端編碼 ≠ 傳輸端宣告 ≠ 消費端解碼」。以 **PHP header() 為主、資料庫連線字元集為本、Meta 為輔** 的三層防禦體系,配合全專案 UTF-8mb4 標準,即可徹底根除亂碼。