2024年PHP开发者大会日本站

字符集

理想情况下,字符集应该在服务器级别设置,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 vs 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(基本多语言平面)之外的字符,例如表情符号或其他特殊字符,则需要使用其他编码,例如utf8mb4或任何其他支持更高平面的编码。Mysql将丢弃任何以4个字节(或更多)编码的字符。

有关此问题的更多信息,请参阅https://dev.mysqlserver.cn/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