1

我有以下问题:在一个非常简单的 php-mysqli 查询上:

if ( $result = $mysqli->query( $sqlquery ) )
{
    $res = $result->fetch_all();
    $result->close();
}

我得到的字符串被错误地编码为西方编码的字符串,尽管数据库、表和列是utf8_general_ci排序规则的。php 脚本本身是 utf-8 编码的,并且脚本的 mysql-less 部分得到了正确的编码。所以说echo "ő"完美,但是echo $res[0]从前面的示例中,EF BF BD当以正确的 UTF-8 编码查看文件时输出字符。如果我手动将浏览器的编码切换为西方,则 mysqli 来源的字符串得到很好的解码,除了非西方字符被替换为“?”。

更奇怪的是,在我的开发环境中没有发生这种情况,而在我的网络服务器上却发生了。开发人员环境是 LAMP 堆栈(统一服务器),而网络服务器使用 nginx。

在这种情况下,我使用 phpMyAdmin 在数据库中输入了数据,并且在 phpmyadmin 中它完美显示。phpMyAdmin 的排序规则也是 utf-8。我相信问题一定是在这里的某个地方,就像在同一个网络服务器上一样,对于我通过 php(使用 POST)输入数据的另一个站点,同样的问题不会发生。在这种情况下,数据在输入和查看数据时都是正确可见的(我的意思是在 php 生成的网页中),但特殊字符在 phpMyAdmin 中不正确。

你能帮我从哪里开始调试吗?它是否连接到phpmysqlnginxphpMyAdmin

4

2 回答 2

1

使用 mysqli::set_charset 函数。

$mysqli->set_charset('utf8'); //returns false if the encoding was not valid... won't happen

http://php.net/manual/en/mysqli.set-charset.php

我已经有一段时间没有使用 mysqli,但如果情况相同,默认情况下连接使用拉丁瑞典编码 (ISO 8859 1)。

我会认为您的页面已经在使用 utf8 编码,方法是:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

<head>标签内。

如果您已经有拉丁瑞典语编码的字符串,您可以使用 mk_convert_encoding:

http://php.net/manual/en/function.mb-convert-encoding.php

$fixedStr = mb_convert_encoding($wrongStr, 'UTF-8', 'ISO-8859-1');

iconv做了一些非常相似的事情:说实话,我不知道有什么区别,但这里是函数参考的链接:http: //php.net/manual/en/function.iconv.php

我刚刚意识到你可能有一些 utf8 和拉丁瑞典语的字符串。您可以为此使用 mb_detect_encoding:http: //php.net/manual/en/function.mb-detect-encoding.php

如果已安装,您还可以转储数据库并使用 iconv(cmd 行):

iconv -f latain -t utf-8 < currentdb.sql > fixeddb.sql
于 2012-10-05T00:27:40.793 回答
1

用于mysqli_set_charset在连接后将客户端编码更改为 UTF-8:

$mysqli->set_charset("utf8");

客户端编码是 MySql 期望您输入的内容(例如,当您将用户提供的文本插入搜索查询时)以及它为您提供的结果(因此它必须匹配您的输出编码才能echo正确显示内容)。

您需要让它与您的网页的编码相匹配,以解决上述两种情况以及PHP 源文件的编码(以便正确解释查询的硬编码部分)。

更新:如何将使用 latin-1 插入的数据转换为 utf-8

对于已经使用错误的连接编码插入的数据,有一个方便的解决方案来解决这个问题。对于包含此类数据的每一列,您需要执行以下操作:

ALTER TABLE table_name MODIFY column_name existing_column_type CHARACTER SET latin1;
ALTER TABLE table_name MODIFY column_name BLOB;
ALTER TABLE table_name MODIFY column_name existing_column_type CHARACTER SET utf8;

占位符table_name,column_name并且existing_column_type每次都应替换为数据库中的正确值。

这是做什么的

  1. 告诉 MySql 它需要将数据存储在 latin1 中的该列中。此字符集仅包含 utf8 的一小部分子集,因此通常此转换涉及数据丢失,但在此特定情况下,数据已在输入时被解释为 latin1,因此不会有副作用。但是,MySql 将在内部转换数据的字节表示以匹配最初从 PHP 发送的内容。
  2. 将该列转换为BLOB没有关联编码信息的二进制类型 ( )。此时,该列将包含作为正确 utf8 字符串的原始字节。
  3. 将列转换为之前的字符类型,告诉 MySql 原始字节应该被认为是 utf8 编码。

警告:如果有问题的列仅包含错误插入的数据,则只能使用这种不分青红皂白的方法。任何已正确插入的数据将在第一次出现任何非 ASCII 字符时被截断!

因此,最好在 PHP 端修复生效之前立即执行此操作。

于 2012-10-05T00:27:52.617 回答