資料表編碼為 UTF-8,但連線預設編碼不一致,導致讀寫時雙向轉碼錯誤,顯示 ???? 或亂碼。
<?php
// 1. 建表指定編碼
$pdo->exec("CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200) NOT NULL,
content TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
// 2. 連線後立即設定連線編碼 (最關鍵)
$pdo->exec("SET NAMES utf8mb4"); // 或 mysqli_set_charset($link, 'utf8mb4')
// 3. 寫入
$stmt = $pdo->prepare("INSERT INTO articles (title, content) VALUES (?, ?)");
$stmt->execute(['測試標題', '測試內容']);
// 4. 讀出
$stmt = $pdo->query("SELECT * FROM articles");
while ($row = $stmt->fetch()) {
echo $row['title']; // 正常顯示中文
}
?>
| 階段 | 動作 |
|---|---|
| 建表 | DEFAULT CHARSET=utf8mb4 (支援 emoji) |
| 連線 | SET NAMES utf8mb4 / mysqli_set_charset() / PDO DSN charset=utf8mb4 |
| 頁面輸出 | header('Content-Type: text/html; charset=utf-8') 或 HTML `` |
| 資料來源 | 確認輸入資料本身為 UTF-8 (表單頁面編碼、檔案編碼、API 回應) |
utf8 而非 utf8mb4:無法儲存 Emoji、生僻字 (MySQL utf8 實為 utf8mb3)SET NAMES gbk,但強烈建議全站統一 UTF-8$dsn = 'mysql:host=127.0.0.1;dbname=test;charset=utf8mb4';
$pdo = new PDO($dsn, 'user', 'pass', [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
]);
// 無需額外 SET NAMES
$pdo->query("SHOW VARIABLES LIKE 'character_set_%'")->fetchAll(PDO::FETCH_KEY_PAIR);
/* 預期結果:
character_set_client => utf8mb4
character_set_connection => utf8mb4
character_set_results => utf8mb4
character_set_database => utf8mb4
character_set_server => utf8mb4
*/