<?php
$link = mysqli_connect('localhost', 'user', 'pass', 'db');
// 推薦:mysqli 物件導向
$mysqli = new mysqli('localhost', 'user', 'pass', 'db');
$mysqli->set_charset('utf8mb4'); // 支援完整 Unicode(含 Emoji)
// 程序式
mysqli_set_charset($link, 'utf8mb4');
// PDO
$pdo = new PDO('mysql:host=localhost;dbname=db;charset=utf8mb4', 'user', 'pass');
?>
SET NAMES utf8 只告訴伺服器「我送 utf8」,但 PHP MySQL 驅動內部狀態未同步,導致 mysql_real_escape_string() 等函式使用錯誤字元集進行跳脫,產生 SQL 注入風險(CVE-2006-3469 類問題)。| 字元集 | 最大字元長度 | 支援 Emoji | 建議 |
|---|---|---|---|
| utf8 (utf8mb3) | 3 bytes | 否 | 舊專案相容 |
| utf8mb4 | 4 bytes | 是 | 新專案預設 |
MySQL 5.5.3+ 完整支援 utf8mb4。資料表、欄位、連線、PHP 端、HTML `` 全鏈路統一 utf8mb4。
<?php
// mysqli 程序式
$link = mysqli_connect('127.0.0.1', 'user', 'pass', 'db', 3306);
if (!$link) die('連線失敗: ' . mysqli_connect_error());
mysqli_set_charset($link, 'utf8mb4');
// PDO(推薦:支援預備語句、多資料庫)
$dsn = 'mysql:host=127.0.0.1;dbname=db;charset=utf8mb4';
$opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false, // 使用真實預備語句
];
$pdo = new PDO($dsn, 'user', 'pass', $opt);
?>
<?php
// mysqli
$res = $mysqli->query('SHOW VARIABLES LIKE "character_set%"');
while ($row = $res->fetch_assoc()) {
echo $row['Variable_name'] . ': ' . $row['Value'] . "\n";
}
// 期望看到 client, connection, results, database 皆為 utf8mb4
// PDO
$stmt = $pdo->query('SELECT @@character_set_client, @@character_set_connection, @@character_set_results');
print_r($stmt->fetch());
?>
**永遠使用 `mysql_set_charset()` / `mysqli::set_charset()` / PDO DSN `charset` 參數**設定連線字元集。棄用 `SET NAMES`、`SET CHARACTER SET`。統一全鏈路 `utf8mb4`,徹底解決中文亂碼與 Emoji 儲存問題,並防範字元集相關 SQL 注入。