PHP Conference Japan 2024

字元集

理想情況下,應在伺服器層級設定適當的字元集,在 MySQL 伺服器手冊的» 字元集設定章節中說明了如何執行此操作。或者,每個 MySQL API 都提供一種在執行階段設定字元集的方法。

注意

字元集與字元跳脫

應理解並定義字元集,因為它會影響每個動作,並包含安全性影響。例如,跳脫機制(例如,mysqli 的 mysqli_real_escape_string() 和 PDO_MySQL 的 PDO::quote())將遵循此設定。重要的是要意識到這些函式不會使用以查詢定義的字元集,因此,例如,以下操作不會對它們產生影響

範例 #1 使用 SQL 設定字元集的問題

<?php

$mysqli
= new mysqli("localhost", "my_user", "my_password", "world");

// 不會影響 $mysqli->real_escape_string();
$mysqli->query("SET NAMES utf8mb4");

// 不會影響 $mysqli->real_escape_string();
$mysqli->query("SET CHARACTER SET utf8mb4");

// 但是,這會影響 $mysqli->real_escape_string();
$mysqli->set_charset('utf8mb4');

// 但是,這不會影響它(UTF-8 與 utf8mb4)-- 此處不要使用破折號
$mysqli->set_charset('UTF-8');
?>

以下範例說明如何使用每個 API 在執行階段正確地變更字元集。

注意可能的 UTF-8 混淆

由於 MySQL 中的字元集名稱不包含破折號,因此字串 "utf8" 在 MySQL 中有效,可將字元集設定為 UTF-8(最多 3 個位元組 UTF-8 Unicode 編碼)。字串 "UTF-8" 無效,因為使用 "UTF-8" 將無法變更字元集並會擲回錯誤。

範例 #2 設定字元集範例:mysqli

<?php
$mysqli
= new mysqli("localhost", "my_user", "my_password", "world");

echo
'初始字元集:' . $mysqli->character_set_name() . "\n";

if (!
$mysqli->set_charset('utf8mb4')) {
printf("載入字元集 utf8mb4 時發生錯誤:%s\n", $mysqli->error);
exit;
}

echo
'您目前的字元集為:' . $mysqli->character_set_name() . "\n";
?>

範例 #3 設定字元集範例:pdo_mysql

<?php
$pdo
= new PDO("mysql:host=localhost;dbname=world;charset=utf8mb4", 'my_user', 'my_pass');
?>
新增註解

使用者貢獻的註解 2 則註解

mkroese at eljakim dot nl
7 年前
請注意,MySQL 的 utf8 編碼最多有 3 個位元組,無法對 *所有* Unicode 字元進行編碼。

如果您需要編碼 BMP(基本多文種平面)以外的字元,例如 emoji 或其他特殊字元,您將需要使用不同的編碼,例如 utf8mb4 或任何其他支援較高平面的編碼。Mysql 會捨棄任何以 4 個位元組(或更多)編碼的字元。

請參閱 https://mysqldev.dev.org.tw/doc/refman/5.7/en/charset-unicode-utf8mb4.html 以取得更多相關資訊
legrand dot jeremie at gmail dot com
1 年前
設定字元集後,您也應該定義「校對」,以提供有關如何在請求中對結果進行排序的資訊。預設情況下,它是「utf8mb4_general_ci」,這是一組簡化的排序規則。對於 Unicode 發布的官方規則,它應該是「utf8mb4_unicode_ci」。

例如
\mysqli_set_charset($hdl, 'utf8mb4');
\mysqli_query($hdl, 'SET collation_connection = utf8mb4_unicode_520_ci');
To Top