中文亂碼本質是 編碼不一致:瀏覽器、HTML 頁面、PHP 文件、MySQL 連線、資料表欄位、資料庫預設編碼——任一環節不匹配即會產生亂碼。
| 層面 | 正確做法 | 常見錯誤 |
|---|---|---|
| HTTP Header | header("Content-Type: text/html; charset=utf-8"); 放在 所有輸出之前 | 有空白行、BOM、echo 在 header 前 |
| HTML Meta | <meta charset="utf-8"> 放在 <head> 首行 | 放在 title 後、或寫成 gb2312 |
| 文件編碼 | 編輯器「另存為」選 UTF-8 無 BOM | ANSI、UTF-8 with BOM |
| BOM 移除 | DW/EditPlus/VS Code 另存為去除 BOM | BOM 導致 session_start 失效 |
-- 1. 建庫指定編碼
CREATE DATABASE `dbname` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
-- 2. 建表指定欄位編碼
CREATE TABLE `test` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
<?php
$conn = mysql_connect($host, $user, $pass);
mysql_select_db($db, $conn);
// 必須在查詢前執行,順序不影響
mysql_query("SET NAMES 'utf8'"); // 讀/寫統一
// 或分開(舊版建議)
mysql_query("SET CHARACTER SET 'utf8'"); // 讀
mysql_query("SET NAMES 'utf8'"); // 寫
?>
<?php
$filename = "中文檔名.pdf";
// 頁面為 UTF-8,下載需轉 GB2312 否則 IE 亂碼
header("Content-Disposition: attachment; filename=" . iconv("UTF-8", "GB2312", $filename));
readfile($path);
?>
function utf8_substr($str, $len) {
$result = '';
for ($i = 0; $i < $len; $i++) {
$char = $str[$i] ?? '';
if (!$char) break;
if (ord($char) > 127) { // 多位元組字符
$result .= $str[$i] . $str[$i+1] . $str[$i+2];
$i += 2;
} else {
$result .= $char;
}
}
return $result;
}
// 或直接用 mb_substr (需開啟 mbstring)
echo mb_substr($str, 0, 10, 'UTF-8');
CHARSET=utf8 / COLLATE=utf8_general_ciheader("Content-Type: text/html; charset=utf-8")<meta charset="utf-8">mysql_query("SET NAMES 'utf8'")default-character-set=utf8「頁面編碼 = 資料庫連線編碼 = 資料表編碼 = 文件儲存編碼 = UTF-8」,只要這條鏈路全線一致,亂碼自然消失。