中文亂碼是 PHP 開發者最常遇到的問題之一。本文系統性分析 PHP、MySQL、瀏覽器三端編碼傳遞鏈路,提供從資料庫設定、連線配置、頁面輸出到除錯診斷的完整解決方案。
<?php
$conn = mysql_connect('localhost', 'root', '000000', 'lib');
$sql = "SELECT name, age FROM mytb";
$rs = mysql_db_query("lib", "SELECT * FROM mytb", $conn);while ($row = mysql_fetch_object($rs)) {
echo $row->name . ": " . $row->age . "<br>";
}
?>
輸出結果:
dd: 54
ddd: 8
??: 15
???: 25
??: 32
資料庫中明明儲存的是中文,卻顯示為問號。
<?php
// 在查詢前加入此行,強制設定連線字元集
mysql_query("SET NAMES 'gb2312'"); // 或 'utf8', 'gbk'
$rs = mysql_db_query("lib", "SELECT * FROM mytb", $conn);
?>
瀏覽器 (HTTP Header / Meta Charset)
↓
PHP 腳本檔案編碼 (UTF-8 無 BOM)
↓
PHP 內部字串處理 (mbstring 設定)
↓
MySQL 連線字元集 (SET NAMES / character_set_connection)
↓
MySQL 資料庫/資料表/欄位預設字元集
↓
MySQL 儲存引擎實際編碼
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | gb2312 | ← 客戶端發送編碼
| character_set_connection | gb2312 | ← 連線轉換編碼 關鍵
| character_set_database | gb2312 | ← 資料庫預設編碼
| character_set_filesystem | binary | ← 檔案系統編碼
| character_set_results | gb2312 | ← 結果集返回編碼 關鍵
| character_set_server | latin1 | ← 伺服器預設編碼
| character_set_system | utf8 | ← 系統識別碼編碼
+--------------------------+--------+
核心原則:character_set_client、character_set_connection、character_set_results 三者必須一致,且支援中文編碼 (utf8/gbk/gb2312/big5)。
-- 建立資料庫時指定字元集
CREATE DATABASE mydb DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;-- 建立資料表時指定字元集
CREATE TABLE mytable (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100)
) DEFAULT CHARSET=utf8mb4;-- 修改既有資料表字元集
ALTER TABLE mytable CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
<?php
$dsn = 'mysql:host=localhost;dbname=mydb;charset=utf8mb4';
$pdo = new PDO($dsn, 'username', 'password', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4'
]);
?>
<?php
$mysqli = new mysqli('localhost', 'username', 'password', 'mydb');
$mysqli->set_charset('utf8mb4');
?>
<?php
$conn = mysql_connect('localhost', 'username', 'password');
mysql_select_db('mydb', $conn);
mysql_query("SET NAMES 'utf8'", $conn); // 或 gbk, gb2312
?>
<?php
// 1. PHP 檔案必須儲存為 UTF-8 無 BOM 編碼
// 2. 設定內部編碼
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
mb_http_input('UTF-8');
mb_language('uni');// 3. 輸出 HTTP 標頭
header('Content-Type: text/html; charset=UTF-8');
?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>中文測試</title>
</head>
<form action="process.php" method="post" accept-charset="UTF-8">
<input type="text" name="name">
<input type="submit" value="送出">
</form>
Content-Type<meta charset="UTF-8">SELECT HEX(column) FROM table 檢查十六進位編碼SHOW VARIABLES LIKE 'character_set_%'| 編碼 | 支援字符 | 適用場景 | 備註 |
|---|---|---|---|
| utf8mb4 | 完整 Unicode (含 Emoji、生僻字) | 新專案首選 | MySQL 5.5.3+ 支援,需 4 位元組儲存 |
| utf8 (utf8mb3) | BMP 字符 (無 Emoji、部分生僻字) | 舊系統相容 | MySQL 內部別名,實為 utf8mb3 |
| gbk/gb2312 | 簡體中文為主 | 舊系統、特定需求 | 不支援繁體、日韓文、Emoji |
| big5 | 繁體中文為主 | 繁體中文舊系統 | 不支援簡體擴展字、Emoji |
結論:新專案統一使用 utf8mb4**,PHP 檔案、資料庫、連線、輸出全鏈路保持一致,即可徹底解決中文亂碼問題。