PHP Conference Japan 2024

mysqli::set_charset

mysqli_set_charset

(PHP 5 >= 5.0.5, PHP 7, PHP 8)

mysqli::set_charset -- mysqli_set_charset设置客户端字符集

描述

面向对象风格

public mysqli::set_charset(string $charset): bool

过程式风格

mysqli_set_charset(mysqli $mysql, string $charset): bool

设置在向数据库服务器发送和接收数据时使用的字符集。

参数

mysql

仅过程式风格:由 mysqli_connect()mysqli_init() 返回的 mysqli 对象

charset

所需的字符集。

返回值

成功时返回 true,失败时返回 false

错误/异常

如果启用了 mysqli 错误报告 (MYSQLI_REPORT_ERROR),并且请求的操作失败,则会生成警告。此外,如果模式设置为 MYSQLI_REPORT_STRICT,则会抛出 mysqli_sql_exception

示例

示例 #1 mysqli::set_charset() 示例

面向对象风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli("localhost", "my_user", "my_password", "test");

printf("初始字符集:%s\n", $mysqli->character_set_name());

/* 将字符集更改为 utf8mb4 */
$mysqli->set_charset("utf8mb4");

printf("当前字符集:%s\n", $mysqli->character_set_name());

过程式风格

<?php

mysqli_report
(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$link = mysqli_connect('localhost', 'my_user', 'my_password', 'test');

printf("初始字符集:%s\n", mysqli_character_set_name($link));

/* 将字符集更改为 utf8mb4 */
mysqli_set_charset($link, "utf8mb4");

printf("当前字符集:%s\n", mysqli_character_set_name($link));

以上示例将输出类似以下内容

Initial character set: latin1
Current character set: utf8mb4

注意

注意:

这是更改字符集的首选方法。不建议使用 mysqli_query() 来设置它(例如 SET NAMES utf8)。有关更多信息,请参阅 MySQL 字符集概念 部分。

参见

添加注释

用户贡献的注释 5 个注释

Konstantin Rozinov
7 年前
Claude 的评论 (https://php.net/manual/en/mysqli.set-charset.php#121067) 是 **正确的**。

在建立连接后,像这样设置字符集(实际上是编码)
$connection->set_charset("utf8mb4")

**无法**为连接设置正确的排序规则

character_set_client: utf8mb4
character_set_connection: utf8mb4
character_set_database: utf8mb4
character_set_filesystem: binary
character_set_results: utf8mb4
character_set_server: utf8mb4
character_set_system: utf8
collation_connection: utf8mb4_general_ci <---- 仍然显示 general
collation_database: utf8mb4_unicode_ci
collation_server: utf8mb4_unicode_ci

如果您使用 SET NAMES,则可以正常工作
$connection->query("SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci");

character_set_client: utf8mb4
character_set_connection: utf8mb4
character_set_database: utf8mb4
character_set_filesystem: binary
character_set_results: utf8mb4
character_set_server: utf8mb4
character_set_system: utf8
collation_connection: utf8mb4_unicode_ci <-- 现在显示 unicode
collation_database: utf8mb4_unicode_ci
collation_server: utf8mb4_unicode_ci

请注意,我在服务器上设置了以下变量

将以下内容设置为:utf8mb4_unicode_ci

character_set_client
character_set_connection
character_set_database
character_set_results
character_set_server

collation_connection
collation_server

设置

character-set-client-handshake = FALSE 或 0
skip-character-set-client-handshake = TRUE 或 1
Emmanuel Appiah
8 年前
在我的情况下,我尝试将 mysql 的排序规则从 utf8mb4_unicode_ci 更改为 uft8_general_ci。



然后粘贴

mysqli_set_charset( $con, 'utf8');

在我执行 SELECT 命令之前。

这是我从数据库读取数据的代码

/*

$DB_SERVER="db_server_name";
$DB_USER_READER="root";
$DB_PASS_READER="passw*rd";
$DB_NAME="db_name";
$DB_PORT="端口号";

$SELECT_WHAT="`表中列的名称`";
$WHICH_TBL="`表名`";
$ON_WHAT_CONDITION="`id`='7'";

*/

$con = mysqli_connect($DB_SERVER, $DB_USER_READER, $DB_PASS_READER, $DB_NAME, $DB_PORT);//这是用于选择的唯一连接

mysqli_set_charset( $con, 'utf8');


$slct_stmnt = "SELECT ".$SELECT_WHAT." FROM ".$WHICH_TBL." WHERE ".$ON_WHAT_CONDITION;

$slct_query = mysqli_query($con, $slct_stmnt);

if ($slct_query==true) {
//在此处执行你的操作...
}

它运行得非常完美。祝一切顺利。以上代码可以读取数据库表列中存储的中文、俄语、阿拉伯语或任何国际语言数据。
claude dot pache at gmail dot com
7 年前
尽管文档说明使用该函数优于使用 SET NAMES,但在使用与默认值不同的排序规则时,它是不够的。

<?php
// 这将重置 collation_connection 为 latin1_swedish_ci
// (latin1 的默认排序规则):
$mysqli->set_charset('latin1');

// 为了获得 collation_connection 的期望值,必须在 mysqli::set_charset() *之后* 执行以下语句:
$mysqli->query("SET NAMES latin1 COLLATE latin1_german1_ci");
ASchmidt at Anamera dot net
6 年前
使字符集(例如,utf8mb4)和排序规则与模式(数据库)设置保持一致

<?php
$mysqli
= new mysqli( DB_HOST, DB_USER, DB_PASSWORD, DB_SCHEMA, DB_PORT );
if (
0 !== $mysqli->connect_errno )
throw new
\Exception( $mysqli->connect_error, $mysqli->connect_errno );

if (
TRUE !== $mysqli->set_charset( 'utf8mb4' ) )
throw new
\Exception( $mysql->error, $mysqli->errno );

if (
TRUE !== $mysqli->query( 'SET collation_connection = @@collation_database;' ) )
throw new
\Exception( $mysql->error, $mysqli->errno );
?>

确认

<?php
echo 'character_set_name: ', $mysqli->character_set_name(), '<br />', PHP_EOL;
foreach(
$mysqli->query( "SHOW VARIABLES LIKE '%_connection';" )->fetch_all() as $setting )
echo
$setting[0], ': ', $setting[1], '<br />', PHP_EOL;
?>

将输出类似以下内容
character_set_name: utf8mb4
character_set_connection: utf8mb4
collation_connection: utf8mb4_unicode_520_ci
chris at ocproducts dot com
6 年前
请注意,根据 PHP 中编译的 MySQL 客户端库,使用此函数的 utf8mb4 可能会导致此函数返回 false。如果客户端库早于 utf8mb4 的引入,则 PHP 对库的 'mysql_set_character_set' 的调用将返回错误,因为它无法识别该字符集。

唯一知道存在错误的方法是检查返回值,因为此函数不会发出 PHP 警告。
mysqli_error 将返回类似以下内容
"无法初始化字符集 utf8mb4 (路径: /usr/share/mysql/charsets/)"
(我认为目录与此无关;我认为 utf8mb4 与 utf8 的区别是在内部处理的)

一种解决方法是用 utf8 重新调用,然后使用 utf8mb4 执行 'SET NAMES' 查询。

如果你的 MySQL 服务器配置为默认使用 utf8,则在遇到一些模糊的错误之前,你可能不会注意到这些问题。从字节的角度来看,它似乎仍然可以正确地保存到数据库中。但是,如果正在截断字符串以适应字段,则可能会收到“列数据过长”错误,因为从 MySQL 的角度来看,在长度检查期间,每个 4 字节字符实际上都是多个单独的字符。这导致我调试了几个小时。
To Top