具有国际字符串的PHP和MySQL最佳实践

时间:2020-03-06 14:47:43  来源:igfitidea点击:

即使将MySQL DB,表和字段的排序规则设置为utf8_general_ci,也经常发生将诸如之类的字符转换为??的情况。页面的Content-Type中的编码也设置为UTF8.

我知道utf8_encode / decode,但是我不确定在哪里以及如何使用它。

我已经阅读了"绝对是每个软件开发人员的绝对最低知识,肯定必须了解Unicode和字符集(没有借口!)"一文,但是我需要一些特定于MySQL / PHP的指针。

问题:如何确保用户输入的包含国际字符的数据不被损坏?

解决方案

没有太多要说的不在本文范围之内

http://developer.loftdigital.com/blog/php-utf-8-cheatsheet

首先看一下http://www.nicknettleton.com/zine/php/php-utf-8-cheatsheet,我认为缺少了一件重要的事情(也许我忽略了这一点)。
根据MySQL安装和/或者配置,我们必须设置连接编码,以便MySQL知道我们期望在客户端使用哪种编码(意味着MySQL连接的客户端,应该是PHP脚本)。我们可以通过手动发出

SET NAMES utf8

发送到MySQL服务器的任何其他查询之前进行查询。

如果我们在PHP端使用PDO,则可以设置连接以使用以下命令在每个(重新)连接上自动发出此查询:

$db=new PDO($dsn, $user, $pass);
$db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES utf8");

初始化数据库连接时。

为了获得更好的unicode正确性,我们应该使用utf8_unicode_ci(尽管文档对这些区别有些含糊)。我们还应该确保正确设置了以下Mysql标志-

  • 默认字符集= utf8
  • skip-character-set-client-handshake //重要提示,因此客户端无需执行其他编码

这些可以在mysql配置文件(在[mysqld]选项卡下)中设置,也可以在运行时通过发送适当的查询来设置。

我们应该做的事情:

  • 确保Apache输出了UTF-8内容。在httpd.conf中执行此操作,或者使用PHP的header()函数手动进行此操作。
  • 确保数据库连接为UTF8. SET NAMES utf8可以解决问题。
  • 确保所有表都设置为UTF8.
  • 如果我们在其中存储了国际字符,请确保所有PHP和模板文件都编码为UTF8.

执行此操作时,通常不需要使用mb_string或者utf8_encode / decode函数来做很多事情。

排序规则和字符集不是一回事。排序规则需要与字符集匹配,因此,如果字符集为utf-8,则排序规则也应如此。选择错误的排序规则不会使数据乱码,尽管只是使字符串比较/排序工作错误。

就是说,有几个地方可以在PHP中设置字符集设置。我建议我们尽可能使用utf-8. 需要指定字符集的位置是:

  • 数据库。可以在数据库,表和字段级别,甚至在每个查询级别上进行设置。
  • PHP和数据库之间的连接。
  • HTTP输出;确保HTTP标头" Content-Type"指定utf-8. 我们可以在PHP和Apache中设置默认值,也可以使用PHP的header函数。
  • HTTP输入。通常,表单将以与提供该页面时相同的字符集提交,但为确保确定,我们应指定accept-charset属性。另外,请确保网址是utf-8编码的,否则请避免在网址(和GET参数)中使用非ascii字符。

utf8_encode/ decode函数的名称有点奇怪。它们专门在latin1(ISO-8859-1)和utf-8之间转换。如果应用程序中的所有内容均为utf-8,则无需过多使用它们。

关于utf-8和PHP至少有两个陷阱。首先是PHP的内置字符串函数期望字符串为单字节。对于很多操作而言,这并不重要,但这意味着我们不能依赖于strlen和其他功能。在此页面上可以很好地了解这些限制。通常,这不是什么大问题,但是尤其是在使用三方库时,我们需要意识到事情可能会因此而崩溃。一种选择是使用mb_string扩展名,该扩展名可以用utf-8感知的替代方法替换所有麻烦的功能。它仍然不是100%防弹的解决方案,但在大多数情况下都可以使用。

另一个问题是,某些PHP安装仍启用了" magic_quotes"设置。此问题与utf-8正交,但可能导致头部刮擦。为了我们自己的理智,请将其关闭。

无论使用哪种语言编写,如果要创建一个允许使用多种编码的应用程序,请分批处理:

  • PHP特别是偷偷摸摸的。不要让它动态地截断数据。如果要对UTF-8字符串进行正则表达式,请确保将其标识为