首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP + MySQL 中文亂碼/問號完整解決方案:編碼三層一致性原則

     編輯:PHP 相關知識

前言

PHP + MySQL 中文亂碼是新手最常遇到的坑。核心原因只有一個:編碼在「資料庫、連線、頁面」三層不一致。本文系統整理編碼三層架構、各層設定方法、常見錯誤場景與對應解法,一次徹底解決亂碼問題。

編碼三層架構

層級對象設定方式檢查指令
1. 儲存層資料庫、資料表、欄位建立時指定 CHARSET=utf8mb4、COLLATE=utf8mb4_unicode_ciSHOW CREATE TABLE tbl
SHOW VARIABLES LIKE 'character_set%'
2. 傳輸層PHP ↔ MySQL 連線DSN charset=utf8mb4、SET NAMES utf8mb4、mysqli_set_charsetSELECT @@character_set_client, @@character_set_connection, @@character_set_results
3. 表現層HTML 頁面、HTTP 回應<meta charset="utf-8">、header('Content-Type: text/html; charset=utf-8')瀏覽器開發工具 Network → Response Headers

鐵律:三層必須完全一致(皆為 utf8mb4 / utf-8),缺一不可。

一、資料庫層設定

-- 建庫
CREATE DATABASE `my_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 建表
CREATE TABLE `users` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

-- 修改既有表/欄位
ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `users` MODIFY `name` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

為何用 utf8mb4? MySQL utf8 實為 utf8mb3,僅支援 3 位元組字符(基本多文種平面),無法儲存 Emoji、生僻字**(需 4 位元組)**。utf8mb4 完整支援 Unicode。

二、連線層設定(PHP 端)

PDO(推薦)

$dsn = 'mysql:host=127.0.0.1;dbname=my_db;charset=utf8mb4';
$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8mb4', // 連線建立時自動執行
];
$pdo = new PDO($dsn, 'user', 'pass', $options);

mysqli 物件導向

$mysqli = new mysqli('127.0.0.1', 'user', 'pass', 'my_db');
if ($mysqli->connect_errno) die('連線失敗');
$mysqli->set_charset('utf8mb4'); // 必須在查詢前呼叫

mysqli 程序式 / 舊版 mysql_*(已移除,僅維護參考)

$link = mysql_connect('127.0.0.1', 'user', 'pass');
mysql_select_db('my_db', $link);
mysql_query("SET NAMES 'utf8mb4'", $link); // 或 'utf8' 若舊版不支援 mb4

三、表現層設定(HTML/HTTP)

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8"> <!-- HTML5 簡寫,等同 http-equiv -->
  <title>中文測試</title>
</head>
<body>...</body>
</html>

或 PHP 輸出 Header(需在任何輸出前):

header('Content-Type: text/html; charset=utf-8');

四、常見亂碼場景與解法

現象原因解決
存入資料庫變 ???? 或亂碼連線層未設定 SET NAMES utf8mb4,MySQL 用預設 latin1 接收PDO DSN 加 charset、mysqli set_charset、舊版 mysql_query("SET NAMES utf8mb4")
讀出顯示 ??? 或亂碼HTML 頁面編碼非 UTF-8(如 Big5/GBK),或 Header 未宣告頁面加 <meta charset="utf-8">,PHP header('Content-Type: text/html; charset=utf-8')
資料庫裡是正確中文,但頁面顯示亂碼連線層、儲存層正確,只有表現層錯修正 HTML meta / HTTP Header
頁面編碼正確,但資料庫存入亂碼表現層、連線層正確,儲存層編碼錯(表/欄位非 utf8mb4)ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4
Emoji 存入變 ???? 或截斷資料表/欄位仍為 utf8 (utf8mb3)全庫轉 utf8mb4,連線層同步 utf8mb4
PHP 檔案本身編碼非 UTF-8編輯器儲存為 Big5/ANSI,字串常數編碼錯IDE 設定「UTF-8 無 BOM」儲存所有 .php 檔
Apache/Nginx 強制預設編碼AddDefaultCharset 或 charset 指令覆蓋 PHP Header關閉或覆蓋:.htaccess: AddDefaultCharset Off 或虛擬主機設定 charset utf-8

五、除錯檢查清單

  1. 資料庫:SHOW CREATE TABLE users 確認 CHARSET=utf8mb4。
  2. 連線:執行 SELECT @@character_set_client, @@character_set_connection, @@character_set_results,三者皆為 utf8mb4。
  3. 頁面:瀏覽器開發工具 → Network → Response Headers → Content-Type: text/html; charset=utf-8。
  4. PHP 檔案:編輯器右下角確認 UTF-8 無 BOM。
  5. 資料流向測試:INSERT 一筆含中文/Emoji → SELECT → var_dump → 瀏覽器顯示,逐層驗證。

六、特殊情況:舊專案無法全面改 utf8mb4

若受限於舊系統必須維持 utf8 (utf8mb3) 或 gbk/big5:

  • 連線層、表現層同步改為該編碼(如 SET NAMES gbk、charset=gbk)。
  • 但強烈建議規劃遷移至 utf8mb4,否則無法支援 Emoji、生僻字,且編碼轉換易出錯。

七、進階:MySQL 伺服器預設編碼設定

修改 my.cnf / my.ini:

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4'

重啟 MySQL 後,新建連線預設即為 utf8mb4,但PHP 端仍需顯式設定,不可依賴伺服器預設。

總結

  1. 資料庫/表/欄位:CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  2. PHP 連線:PDO DSN charset=utf8mb4 + MYSQL_ATTR_INIT_COMMAND=SET NAMES utf8mb4 / mysqli->set_charset('utf8mb4')
  3. HTML 頁面:<meta charset="utf-8"> + header('Content-Type: text/html; charset=utf-8')
  4. PHP 檔案:UTF-8 無 BOM 儲存。
  5. 伺服器:關閉 AddDefaultCharset 或設為 utf-8。

三層一致,亂碼自消。遇到問題按「儲存→傳輸→表現」順序逐層驗證,必能定位根因。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved