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

PHP 中文亂碼與 MySQL 中文亂碼完整解決方案

     編輯:PHP 相關知識

PHP 與 MySQL 中文編碼問題完整解析

中文亂碼是 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 字元集系統變數詳解

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)。

完整解決方案清單

1. 資料庫層面設定

-- 建立資料庫時指定字元集
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;

2. PHP 連線層面設定 (PDO 推薦)

<?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'
]);
?>

3. PHP 連線層面設定 (mysqli)

<?php
$mysqli = new mysqli('localhost', 'username', 'password', 'mydb');
$mysqli->set_charset('utf8mb4');
?>

4. PHP 連線層面設定 (舊版 mysql_* - 不推薦)

<?php
$conn = mysql_connect('localhost', 'username', 'password');
mysql_select_db('mydb', $conn);
mysql_query("SET NAMES 'utf8'", $conn); // 或 gbk, gb2312
?>

5. PHP 檔案與輸出設定

<?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>

6. HTML 表單傳輸設定

<form action="process.php" method="post" accept-charset="UTF-8">
  <input type="text" name="name">
  <input type="submit" value="送出">
</form>

除錯診斷步驟

  1. 確認 PHP 檔案編碼:使用編輯器查看/轉換為 UTF-8 無 BOM
  2. 確認 HTTP 回應標頭:瀏覽器開發工具 Network 面板檢查 Content-Type
  3. 確認 HTML meta 標籤:<meta charset="UTF-8">
  4. 確認資料庫實際儲存編碼:SELECT HEX(column) FROM table 檢查十六進位編碼
  5. 確認連線字元集:SHOW VARIABLES LIKE 'character_set_%'
  6. 隔離測試:直接在 MySQL Client 執行查詢,排除 PHP 層面問題

編碼選擇建議:utf8mb4 vs utf8 vs gbk

編碼支援字符適用場景備註
utf8mb4完整 Unicode (含 Emoji、生僻字)新專案首選MySQL 5.5.3+ 支援,需 4 位元組儲存
utf8 (utf8mb3)BMP 字符 (無 Emoji、部分生僻字)舊系統相容MySQL 內部別名,實為 utf8mb3
gbk/gb2312簡體中文為主舊系統、特定需求不支援繁體、日韓文、Emoji
big5繁體中文為主繁體中文舊系統不支援簡體擴展字、Emoji

結論:新專案統一使用 utf8mb4**,PHP 檔案、資料庫、連線、輸出全鏈路保持一致,即可徹底解決中文亂碼問題。

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