gpt4 book ai didi

php - 执行 mysqli->set_charset() 的永久方法?

转载 作者:IT老高 更新时间:2023-10-29 00:03:40 24 4
gpt4 key购买 nike

在将我能找到的字符集的所有配置文件和运行时选项设置为 utf-8 后,使用 php 建立的新 mysqli 连接仍将其字符集设置为 latin1,这实际上意味着我必须调用 $mysqli->set_charset('utf8') 每次连接时。

$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);  
if ($mysqli->connect_error)
err_handle("mysql connect error({$mysqli->connect_errno}).");
if (!$mysqli->set_charset("utf8"))
err_handle("db error({$mysqli->errno}).");

我想知道是否有永久的方法可以做到这一点?

this post 中遇到过类似问题.


在调用 $mysqli->set_charset('utf8') 之前在 mysql 服务器上进行“show variables like 'character_set%'”查询显示:
(这部分在以前的版本中是模棱两可的)

character_set_client    latin1  
character_set_connection latin1
character_set_database utf8
character_set_filesystem binary
character_set_results latin1
character_set_server utf8
character_set_system utf8

客户端、连接和结果字符集只能在运行时使用 $mysqli->set_charset('utf8') 更改为 utf8。之后它显示:

character_set_client    utf8  
character_set_connection utf8
character_set_database utf8
character_set_filesystem binary
character_set_results utf8
character_set_server utf8
character_set_system utf8

我有

default_charset = "utf-8"

在php.ini中设置,

[client]  
default-character-set=utf8
...
[mysqld]
## This option is deprecated in favor of --character-set-server.
#default-character-set=utf8

在 my.cnf 中设置。

我的表格的默认字符集也是 utf8。

似乎“[client]”选项只影响cmd“mysql”工具,与php无关。

无论我做什么,$mysqli->character_set_name()的返回值总是latin1,直到$mysqli->set_charset('utf8' ) 被调用。

我猜“latin1”是 mysql 的东西,因为我不记得在我的系统上默认为“latin1”的任何其他内容。

^更新: 根据mysql手册9.1.4 , 9.1.55.1.3 , character_set_client 应由客户端提供。我猜php在连接时没有提供它,而mysql使用后备字符集latin1

我正在使用 mysql 5.1 在 debian wheezy 上运行 php 5.3。

有什么建议吗?


更新了评论中的信息:

我忘了提及 skip-character-set-client-handshake 指令以及为什么我不愿意使用它。

乍一看,我认为忽略握手可能会导致客户端说 latin1 而服务器说 utf8 的情况。服务器如何在不知道当前使用的字符集的情况下将字符串从字符集 character_set_client 转换为 character_set_server

如果我错了,请纠正我,请。 我将在今天晚些时候尝试这个设置,看看它是否有效。

更新了workaroud:

确保一切都在 utf-8(或任何首选字符集)下工作。然后将 skip-character-set-client-handshake 行添加到 my.cnf

到目前为止,这对我有用。我尝试了一些双宽 utf-8 字符。 insertselect 均成功并在浏览器中正确显示。

跳过握手意味着什么还不清楚。并且 mysql 服务器现在无法使用除 utf-8 之外的任何字符集,这使得这种解决方法非常不切实际,因为我无法将此设置应用于我的网站运行的所有服务器。

所以我没有采用这种解决方法。非常感谢您的进一步评论和回答。

最佳答案

您已正确诊断出基本问题:虽然您可以在客户端机器的 my.cnf.my.cnf 中更改默认 MySQL 客户端字符集,但这些文件是PHP 不使用。

如果您考虑一下 PHP 的 MySQLi/MySQL 扩展是如何工作的,这将是有道理的——它们与 mysql 客户端程序无关,并且不会爬取您的文件系统以获取配置文件,因为他们直接使用libmysql

要更改 libmysql 的实际默认字符集,您只需重建 libmysql。这可能不是您喜欢的答案(因为您使用的是预编译的 MySQL 二进制文件),但它是实际答案。默认值是在编译时设置的,然后可以在运行时覆盖。

如果您不想这样做并且调用 set_charset() 会惹恼您,我的建议是简单地扩展 MySQLi 类并使用该类代替 mysqli。即:

class MyDB extends mysqli {
// (You could set defaults for the params here if you want
// i.e. $host = 'myserver', $dbname = 'myappsdb' etc.)
public function __construct($host = NULL, $username = NULL, $dbname = NULL, $port = NULL, $socket = NULL) {
parent::__construct($host, $username, $dbname, $port, $socket);
$this->set_charset("utf8");
}
}

通常在一个应用程序中,无论如何你都会有某种数据库抽象层,所以你可以让这个层使用 MyDB 而不是 mysqli,或者你可以让这个层 be MyDB 并添加或覆盖任何你想要的方法(我已经用简单的 ORM-less 应用程序完成了这个)。

最好始终拥有某种数据库抽象层,即使它只是从 class MyDB extends mysqli {} 开始,因为这样您就不必搜索/替换整个代码库做些小改动。

RE:正如您所解释的,您的解决方法基本上将您的整个数据库服务器硬编码为 UTF-8,而不管客户端请求什么。服务器不是拥有多个数据库,每个数据库都有自己的字符集,而是只使用 UTF-8,并且如果客户端连接到另一个字符集,它可能会默默地破坏数据。这从根本上来说是错误的,因为您已经有效地将应用程序配置(数据库字符集)的一个方面从应用程序/客户端机器移到了它并不真正属于的数据库服务器。

如果您考虑应用程序堆栈的层,

[server] <=> [network] <=> [client libmysql] <=> [PHP binary] <=> [app]

然后您就会明白,像这样的应用特定配置的“正确”位置是应用本身,而不是堆栈中的其他位置。您可能不喜欢在 PHP 中指定数据库的字符集,但如果您考虑一下,那确实是它所属的地方,因为它也是您指定要连接到的数据库本身的地方——它是一个连接参数,不是服务器配置问题。在其他任何地方硬编码字符集会使您的应用程序不可移植。

关于php - 执行 mysqli->set_charset() 的永久方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5842980/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com