当前位置:  开发笔记 > 编程语言 > 正文

做mysqli-> set_charset()的永久方法?

如何解决《做mysqli->set_charset()的永久方法?》经验,为你挑选了1个好方法。

设置了我可以找到utf-8的charset的所有配置文件和运行时选项之后,用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}).");

我想知道是否有永久的方式这样做?

在这篇文章中遇到了类似的问题.


show variables like 'character_set%'在调用show之前在mysql服务器上发出一个" "查询$mysqli->set_charset('utf8'):(
这部分在之前的版本中含糊不清)

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.5和5.1.3,character_set_client应该由客户端提供.我猜php在连接时没有提供它,而mysql使用了后备charset latin1.

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

有什么建议吗?


更新了评论信息:

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

乍一看,我认为忽略握手可能会导致客户端在服务器会话utf8时会latin1的情况.服务器如何将字符串从charset转换为不知道当前正在使用的字符集?character_set_clientcharacter_set_server

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

更新了workaroud:

确保一切都在utf-8(或任何更好的字符集)下工作.然后添加skip-character-set-client-handshakemy.cnf.

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

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

所以我不采用这种解决方法.进一步的意见和答案非常感谢.



1> joelhardi..:

你已经正确诊断的基本问题:虽然您可以更改客户端计算机的默认MySQL客户端字符集my.cnf或者.my.cnf,这些文件不使用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,或者你可以让这个层 MyDB并添加或覆盖你想要的任何方法(我已经完成了)这与简单的无ORM应用程序).

总是拥有某种数据库抽象层是一种很好的做法,即使它只是class MyDB extends mysqli {}因为你将永远不必搜索/替换整个代码库来进行小的更改.

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

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

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

然后你会明白,像这样的特定于应用程序的配置的"正确"位置是在应用程序本身,而不是堆栈中的其他位置.你可以不喜欢有在PHP中指定数据库的字符集,但如果你仔细想想,这真的属于它的地方,因为它也是在那里你指定要连接到数据库本身 - 这是一个连接参数,不是服务器配置问题.在其他任何地方对字符集进行硬编码会使您的应用程序无法移植.

推荐阅读
k78283381
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有