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

PHP 連接 MySQL 中文亂碼徹底解決方案:編碼一致性三部曲

     編輯:PHP 綜合知識

亂碼根本原因

**編碼不一致**導致資料在「資料庫 → 連線 → PHP → 瀏覽器」傳輸鏈路中錯誤轉碼。核心三點必須**完全一致**:

  1. 資料庫/表/欄位編碼(建議 `utf8mb4`)
  2. PHP 腳本檔案儲存編碼(UTF-8 without BOM)
  3. HTTP 回應標頭 `Content-Type: text/html; charset=utf-8`
  4. MySQL 連線編碼設定 (`SET NAMES utf8mb4`)

標準解決三步驟

1. 資料庫層面設定 utf8mb4(支援 Emoji、完整 Unicode)

-- 建庫時指定
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;

-- 修改既有庫/表
ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

2. PHP 連線建立時設定字元集

<?php
// MySQLi 面向物件
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
if ($mysqli->connect_errno) die('連線失敗: ' . $mysqli->connect_error);
// 關鍵:設定連線編碼
$mysqli->set_charset('utf8mb4');

// PDO
$pdo = new PDO('mysql:host=localhost;dbname=db;charset=utf8mb4', 'user', 'pass', [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);
// DSN 中 charset=utf8mb4 等同 SET NAMES,PHP 5.3.6+ 支援
?>

舊版寫法(不推薦):`$mysqli->query("SET NAMES utf8mb4");` 或 `mysql_query("SET NAMES utf8");`—— 繞過驅動層,可能導致預處理語句編碼異常。

3. HTTP 回應標頭與檔案編碼

<?php
// 必須在任何輸出之前
header('Content-Type: text/html; charset=utf-8');
// 或 nginx/Apache 配置預設 charset
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"> <!-- HTML5 簡寫 -->
</head>
...

**編輯器儲存時選擇 UTF-8 without BOM**(VS Code、PhpStorm、Notepad++ 皆可設定)。

驗證檢查清單

<?php
// 1. 檢查連線變數
$mysqli->query("SHOW VARIABLES LIKE 'character_set_%'");
// 期望:client, connection, results, database, server 皆為 utf8mb4

// 2. 寫入測試
$mysqli->query("INSERT INTO test (col) VALUES ('中文測試😀')");

// 3. 讀取測試
$result = $mysqli->query("SELECT col FROM test");
$row = $result->fetch_assoc();
echo $row['col']; // 頁面正常顯示「中文測試😀」即成功
?>

常見誤區與避坑

誤區後果正確做法
只加 `header('charset=utf-8')` 不設連線編碼資料庫存正確,讀出亂碼(連線預設 latin1)必須 `set_charset('utf8mb4')`
用 `utf8` 而非 `utf8mb4`無法儲存 Emoji、部分生僻字(MySQL utf8 為 utf8mb3)全鏈路用 `utf8mb4`
檔案儲存為 ANSI/GBK/UTF-8 with BOMBOM 導致 `header()` 失效、輸出異常統一 UTF-8 without BOM
資料庫編碼正確但表/欄位仍為 latin1新資料正常,舊資料亂碼`ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4`
PDO DSN 未加 `charset=utf8mb4` 靠 `SET NAMES`預處理語句參數綁定可能編碼錯誤DSN 明確指定 charset

深度原理:MySQL 字元集系統變數

SHOW VARIABLES LIKE 'character_set_%';
/*
character_set_client      → 客戶端發送 SQL 的編碼
character_set_connection  → 連線層轉換目標編碼
character_set_results     → 結果集返回給客戶端的編碼
character_set_database    → 當前資料庫預設編碼
character_set_server      → 服務器預設編碼
character_set_system      → 系統標識符編碼 (固定 utf8)
*/

-- SET NAMES utf8mb4 等同於:
SET character_set_client = utf8mb4;
SET character_set_results = utf8mb4;
SET character_set_connection = utf8mb4;

若這三個變數與資料實際編碼不一致,中間轉換會造成資料損壞(不可逆)。

總結

**「編碼一致性三部曲」**:資料庫 `utf8mb4`、連線 `set_charset('utf8mb4')`、輸出 `header('charset=utf-8')` + 檔案 `UTF-8 without BOM`。缺一不可。現代專案**一律採用 utf8mb4**,棄用 `utf8`/`latin1`,從建庫、連線、輸出全鏈路統一,徹底杜絕中文亂碼。

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