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

PHP 連接 MySQL 中文亂碼徹底解決:三層編碼一致性原則

     編輯:PHP 相關知識

核心原則:三層編碼必須一致

  1. 資料庫/資料表/欄位編碼:建議全用 utf8mb4(支援 Emoji)
  2. PHP 檔案儲存編碼:編輯器另存為 UTF-8 無 BOM
  3. 網頁輸出編碼:<meta charset="utf-8"> + HTTP Header Content-Type: text/html; charset=utf-8
  4. 連線編碼:執行 SET NAMES utf8mb4(或 utf8)

任一層不一致 → 亂碼(問號 、亂碼 、雙重編碼)。

完整設定檢查清單

1. 資料庫層

-- 建庫指定
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 建表指定
CREATE TABLE users (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(50)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 檢查現有編碼
SHOW VARIABLES LIKE 'character_set_%';
SHOW CREATE TABLE users;

2. PHP 連線層

<?php
// mysqli 物件導向(推薦)
$mysqli = new mysqli('localhost', 'user', 'pwd', 'mydb');
if ($mysqli->connect_errno) {
    die("連線失敗: " . $mysqli->connect_error);
}
// 關鍵:設定連線編碼
$mysqli->set_charset('utf8mb4'); // 等同 SET NAMES utf8mb4

// PDO(推薦)
$pdo = new PDO(
    'mysql:host=localhost;dbname=mydb;charset=utf8mb4',
    'user', 'pwd',
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4"
    ]
);

注意:PDO DSN 中的 charset=utf8mb4 (PHP 5.3.6+) 已足夠,但加上 MYSQL_ATTR_INIT_COMMAND 更保險。

3. 網頁輸出層

<?php
// 最早送出 Header(在任何輸出前)
header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>中文測試</title>
</head>
<body>
  <?php echo "中文顯示正常"; ?>
</body>
</html>

深度解析:SET NAMES 背後做了什麼?

SET NAMES utf8mb4;
-- 等同於執行以下三條:
SET character_set_client = utf8mb4;    -- 客戶端送出的 SQL 編碼
SET character_set_connection = utf8mb4; -- 連線層轉換編碼
SET character_set_results = utf8mb4;    -- 伺服器回傳結果編碼

資料流向:

Client (UTF-8) → character_set_client → Server (utf8mb4)
Server (utf8mb4) → character_set_results → Client (UTF-8)

若中間任一環節為 latin1,中文會經過「UTF-8 → latin1 → UTF-8」不可逆轉換,導致資料損毀。

常見誤區與排查

現象可能原因檢查重點
存入資料庫顯示 ??? 連線編碼錯誤(未 SET NAMES)$mysqli->set_charset()、PDO DSN charset
讀出資料庫顯示 網頁輸出編碼非 UTF-8Header、meta charset、檔案儲存編碼
資料庫裡已是亂碼寫入時連線編碼錯匯出 SQL 檢查、重新匯入前修正連線
Emoji 變 ????資料庫用 utf8 而非 utf8mb4ALTER TABLE ... CHARSET=utf8mb4

舊專案快速修復腳本

<?php
// 批次轉換資料表編碼
$pdo = new PDO('mysql:host=localhost;dbname=old_db', 'root', 'pwd');
$tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $table) {
    $pdo->exec("ALTER TABLE `{$table}` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
    echo "已轉換: {$table}\n";
}
$pdo->exec("ALTER DATABASE `old_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
echo "資料庫編碼已更新\n";

最佳實踐總結

  1. 新專案一律 utf8mb4 + utf8mb4_unicode_ci
  2. PHP 連線**建立瞬間**即設定 charset(mysqli::set_charset / PDO DSN)
  3. HTTP Header + meta charset 雙重保險
  4. 編輯器、IDE、版控 全強制 UTF-8 無 BOM
  5. 定期檢查 SHOW VARIABLES LIKE 'character_set_%' 確認運行期一致

遵循「三層一致」,中文亂碼將成為歷史。

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