UTF-8 一路通过

共14个回答,已解决, 标签: php mysql linux apache utf-8

我正在设置一个新服务器, 并希望在我的 web 应用程序中完全支持 UTF-8。我过去曾在现有的服务器上尝试过, 最终似乎总是不得不回到 iso-8859-1。

我需要在哪里设置编码字符集?我知道我需要配置 Apache、MySQL 和 PHP 来执行此操作-是否有一些标准的检查表, 我可以遵循, 或者可能是在发生不匹配的地方进行故障排除?

这适用于运行 MySQL 5、PHP、5 和 Apache 2 的新 linux 服务器。

第1个答案(采用)

数据存储:

  • 指定 utf8mb4 数据库中所有表和文本列上的字符集。 这使得 MySQL 能够物理地存储和检索在 UTF-8 中本地编码的值。 请注意, utf8mb4 如果 utf8mb4_* 指定了排序规则 (不包含任何显式字符集), MySQL 将隐式使用编码。

  • 在旧版本的 mysql< 5.5.3),="" you'll="" unfortunately="" be="" forced="" to="" use="" simply="">中 utf8 (它只支持 unicode 字符的子集)。 我真希望我是在开玩笑。

数据访问:

  • 在应用程序代码 (例如 PHP) 中, 无论使用何种 DB 访问方法, 都需要将连接字符集设置为 utf8mb4 。 这样, MySQL 在将数据传递到应用程序时, 不会从其原生 UTF-8 进行转换, 反之亦然。

  • 某些驱动程序提供了自己的连接字符集配置机制, 该机制既更新其自身的内部状态, 又通知 MySQL 要在连接上使用的编码, 这通常是首选方法。 在 PHP 中:

    • 如果您使用的是 php≥5.3.6 的Pdo抽象层, 则可以 charsetdsn中指定:

      $dbh = new PDO('mysql:charset=utf8mb4');
      
    • 如果您使用的是 mysqli, 您可以 set_charset() 拨打:

      $mysqli->set_charset('utf8mb4');       // object oriented style
      mysqli_set_charset($link, 'utf8mb4');  // procedural style
      
    • 如果你被简单的 mysql 卡住了, 但恰好正在运行 php≥5.2.3, mysql_set_charset 你可以打电话。

  • 如果驱动程序没有提供自己的连接字符集设置机制, 则可能需要发出查询, 告知 MySQL 应用程序希望如何对连接上的数据进行编码: SET NAMES 'utf8mb4'

  • 关于 utf8mb4 utf8 /适用于上述相同的考虑。

输出:

  • 如果您的应用程序将文本传输到其他系统, 则还需要向它们通报字符编码。 对于 web 应用程序, 必须通知浏览器发送数据的编码 (通过 HTTP 响应标头或html 元数据)。

  • 在 php 中, 您可以 default_charset 使用 php. ini 选项, 也 Content-Type 可以自己手动颁发 mime 标头, 这只是更多的工作, 但具有相同的效果。

输入:

  • 遗憾的是, 在尝试将每个接收的字符串存储或在任何位置使用之前, 应将其验证为有效的 UTF-8。 Php mb_check_encoding() 的方法, 但你必须使用它的宗教。 真的没有办法解决这个问题, 因为恶意客户端可以以他们想要的任何编码提交数据, 我还没有找到一个技巧, 让 PHP 为您可靠地做到这一点。

  • 从我对当前html 规范的阅读中, 下面的子项目符号不是必需的, 也不是

第2个答案

我想在chazomaticus 的很好的回答中补充一点:

也不要忘记 META 标记 (如下所示, 或HTML4 或 xhtml 版本):


这似乎微不足道, 但 IE7 之前给了我这样的问题。

我做的一切都是对的;数据库、数据库连接和内容类型 http 标头都设置为 UTF-8, 并且在所有其他浏览器中都工作正常, 但 Internet Explorer 仍然坚持使用 "西欧" 编码。

原来, 该页面缺少 META 标签。添加解决了问题。

编辑:

W3C 实际上有一个相当大的部分专门用于 I18N。他们有许多与此问题相关的文章--描述 HTTP、(X) HTML 和 CSS 方面的内容:

他们建议同时使用 HTTP 标头和 HTML 元标记 (或 XML 声明 (在 XHTML 中充当 XML)。

第3个答案

除了 default_charset 在 php. ini 中进行设置外, 您还可以在任何输出之前, 使用代码中的正确字符集 header() 发送:

header('Content-Type: text/html; charset=utf-8');

只要您意识到大多数字符串函数不使用 Unicode, 并且有些函数可能会完全处理字符串, 那么在 php 中使用 Unicode 就很容易.PHP 认为 "字符" 有 1 个字节长。有时这是可以的 (例如, explode() 只查找字节序列并将其用作分隔符--因此, 您查找的实际字符并不重要)。但其他时候, 当函数实际上设计为处理字符时, php 不知道您的文本具有使用 unicode 找到的多字节字符。

一个很好的库, 检查到是 phputf8。这将重写所有 "坏" 函数, 以便您可以安全地处理 UTF8 字符串。有一些扩展, 如 mbstring 扩展, 试图为您做到这一点, 太, 但我更喜欢使用库, 因为它更便携 (但我写大众市场的产品, 所以这对我很重要)。但无论如何, phputf8 可以在幕后使用 mbstring 来提高性能。

第4个答案

老话题, 我知道。发现有人使用 PDO 有问题, 答案是将此用于 PDO 连接字符串:

$pdo = new PDO(
    'mysql:host=mysql.example.com;dbname=example_db',
    "username",
    "password",
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

我把这个下来的网站是下来的, 幸运的是能够得到它使用谷歌缓存。

第5个答案

在我的例子中, 我使用 mb_split 的是正则表达式。 因此, 我还必须手动确保正则表达式编码是 utf-8 通过做mb_regex_encoding('UTF-8');

作为一个附带说明, 我还通过运行 mb_internal_encoding() 发现内部编码不是 utf-8, 我通过运行来改变它 mb_internal_encoding("UTF-8");

第6个答案

首先, 如果你是在< 5.3php="" then="" no.="" you've="" got="" a="" ton="" of="" problems="" to="" tackle.="">

我很惊讶, 没有人提到国际文库, 一个有很好的支持 unicode, 图形, 字符串操作,本地化和更多, 见下文。

我将引用一些关于在Phpbenelux14 伊丽莎白·史密斯的幻灯片在 php 中支持 unicode 的信息

国际

好:

  • ICU 图书馆周围的包装器
  • 标准化区域设置, 为每个脚本设置区域设置
  • 数字格式
  • 货币格式
  • 邮件格式 (替换 gettext)
  • 日历、日期、时区和时间
  • 音译机
  • 斯普检查器
  • 资源包
  • 变流器
  • IDN 支持
  • 显卡
  • 整理
  • 迭代器

坏:

  • 不支持 zend _ 多重咬合
  • 不支持 HTTP 输入输出转换
  • 不支持功能重载

mb _ string

  • 启用 zend _ 多字节支持
  • 支持透明的 HTTP 输入编码
  • 提供一些可用于功能的包装, 如 strtoupper

ICOV

  • 主要用于字符集转换
  • 输出缓冲区处理程序
  • 哑剧编码功能
  • 转换
  • 一些字符串助手 (len, substr, strpos, str 尔 pos)
  • 流筛选器stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')

数据库

  • mysql: 表和连接上的字符集和排序规则 (而不是排序规则)。也不要使用 mysql-msqli 或 PDO
  • postarql:pg _ set _ client _ 编码
  • sqlite(3): 确保它是用 unicode 和 intl 支持编译的

其他一些哥特查斯

  • 除非使用第三部分扩展名, 否则不能将 unicode 文件名与 PHP 和窗口一起使用。
  • 如果您使用的是 exec、proc _ open 和其他命令行调用, 请在 ASCII 中发送所有内容
  • 纯文本不是纯文本, 文件有编码
  • 您可以使用图标筛选器动态转换文件

我将更新此答案, 以防添加的功能发生更改等。

第7个答案

我最近发现, 使用 strtolower() 可能会导致数据在特殊字符后被截断的问题。

解决的办法是使用

mb_strtolower($string, 'UTF-8');

mb _ 使用多字节。它支持更多字符, 但通常速度稍慢一些。

第8个答案

我唯一要添加到这些惊人的答案是强调保存您的文件在 utf8 编码, 我已经注意到, 浏览器接受此属性超过设置 utf8 作为您的代码编码。任何像样的文本编辑器将告诉你这一点, 例如记事本 ++ 有一个菜单选项的文件编码, 它显示你当前的编码, 并使您能够改变它。对于我所有的 php 文件, 我使用 utf8 没有 BOM。

前段时间, 我有人要求我添加 utf8 支持的 php/mysql 应用程序设计的其他人, 我注意到, 所有的文件都编码在 ANSI, 所以我不得不使用 ICONV 转换所有文件, 更改数据库表使用 utf8 charset 和 utf8_general_ci coll 在连接后, 将 "SET NAME UTF8" 添加到数据库抽象层 (如果使用 5.3.6 或更早, 则必须在连接字符串中使用 charsetceschutf8), 并更改字符串函数以使用等效的 php 多字节字符串函数。

第9个答案

在 PHP 中, 您需要使用多字节函数, 或者打开mbstring. func _ 重载。这样, 如果你有一个以上字节的字符, 像 strlen 这样的事情就会起作用。

您还需要确定响应的字符集。您可以使用上面的 Addefaultcharset, 也可以编写返回标头的 PHP 代码。(或者, 您也可以将 META 标记添加到 HTML 文档中。

第10个答案

我刚刚经历了同样的问题, 在 PHP 手册中找到了一个很好的解决方案。

我将所有文件编码更改为 UTF8, 然后将连接上的默认编码。这解决了所有的问题。

if (!$mysqli->set_charset("utf8")) {
    printf("Error loading character set utf8: %s\n", $mysqli->error);
} else {
   printf("Current character set: %s\n", $mysqli->character_set_name());
}

查看源

第11个答案

PHP 中的 Unicode 支持仍然是一个巨大的混乱。虽然它能够将 ISO8859 字符串 (在内部使用) 转换为 utf8, 但它缺乏在本地使用 unicode 字符串的能力, 这意味着所有字符串处理函数都将处理和损坏您的字符串。因此, 您必须使用单独的库才能获得适当的 utf8 支持, 或者自己重写所有字符串处理函数。

简单的部分只是在 HTTP 标头和数据库中指定字符集, 但如果 PHP 代码不能输出有效的 UTF8, 这些都不重要。这是最困难的部分, PHP 几乎没有给你任何帮助。(我认为 PHP6 应该解决最糟糕的问题, 但这还需要一段时间)

第12个答案

最重要的答案是优秀的。以下是我在常规 debian/php/mysql 设置上必须做的事情:

// storage
// debian. apparently already utf-8

// retrieval
// the mysql database was stored in utf-8,
// but apparently php was requesting iso. this worked:
// ***notice "utf8", without dash, this is a mysql encoding***
mysql_set_charset('utf8');

// delivery
// php.ini did not have a default charset,
// (it was commented out, shared host) and
// no http encoding was specified in the apache headers.
// this made apache send out a utf-8 header
// (and perhaps made php actually send out utf-8)
// ***notice "utf-8", with dash, this is a php encoding***
ini_set('default_charset','utf-8');

// submission
// this worked in all major browsers once apache
// was sending out the utf-8 header. i didnt add
// the accept-charset attribute.

// processing
// changed a few commands in php, like substr,
// to mb_substr

仅此而已!

第13个答案

如果您希望 MySQL 服务器决定字符集, 而不是 PHP 作为客户端 (旧行为; 在我看来首选), 请尝试添加 skip-character-set-client-handshake 到您的 my.cnf , [mysqld] 下, 然后重新启动 mysql

如果您使用的不是 UTF8, 这可能会导致麻烦。

第14个答案

如果你想要一个 mysql 解决方案, 我有类似的问题与我的两个项目, 后服务器迁移。在搜索和尝试了很多解决方案后, 我遇到了这个-没有这个工作之前):

mysqli_set_charset($con,"utf8");

将这一行添加到我的配置文件后, 一切工作正常!

我发现这个解决方案https://www.w3schools.com/PHP/func_mysqli_set_charset.asp , 当我正在寻找解决从 html 查询插入

祝你好运!

相关问题

mysql _ 拿给数组 ()/mysql_fetch_assoc ()/mysql_fetch_row ()/mysql_num_rows 等希望参数1是资源或结果 参考-此错误在 PHP 中意味着什么? 如何在 PHP 中分析和处理 HTML\ xml? 如何防止 PHP 中的 SQL 注入? UTF-8 一路通过 错误: TCP 提供程序: 错误代码 0x2746。在 linux 下通过终端进行 Sql 设置时 为什么是统计:: st _ size 0 为设备, 但同时 lseek 正确地定义了设备大小? 从节点 js 网站 url 中删除端口 PHP 在 php.Ini文件上做任何解析吗? 使用 League/CSV 导出 CSV 不会对 umlauts 进行编码