PHP/MySQL 编码问题

5

我在PHP编码方面遇到了问题。

我的JavaScript/jQuery HTML5页面通过$.post与我的PHP脚本进行交互。然而,PHP遇到了一个奇怪的问题,可能与编码有关。

当我写下以下代码时:

htmlentities("í")

我希望PHP输出í。但是,它输出的是í

一开始,我以为是编码出了问题,然而

htmlentities("í")=="í"?"Good":"Fail";

输出的是“失败(Fail)”,其中
htmlentities("í")=="í"?"Good":"Fail";

但是htmlentities($search, null, "utf-8")按预期工作。

我希望PHP能够与MySQL服务器通信,但即使使用utf8_encode,也会出现编码问题。我该怎么办?

编辑:在SQL命令中,写入

SELECT id,uid,type,value FROM users,profile
WHERE uid=id AND type='name' AND value='XXX';

如果 XXX 中不包含 'í' 字符,则正常工作,但如果存在任何 'í' 字符,则无法正常工作。

SET NAMES 'utf8';
SET CHARACTER SET 'utf8';
SELECT id,uid,type,value FROM users,profile
WHERE uid=id AND type='name' AND value='XXX';

不仅对于含有 í 字符的字符串无法工作,而且对于没有任何“特殊”字符的字符串也无法工作。从 SET NAMES 和 SET CHARACTER SET 中删除 ' 字符似乎并没有改变任何内容。

我正在使用 PDO 连接到 MySQL 数据库。

编辑 2:我正在使用 XAMPP for Linux 的 MySQL 版本 5.1.30。

编辑 3:从 PhpMyAdmin 运行 SHOW VARIABLES LIKE '%character%' 输出:

character_set_client    utf8
character_set_connection    utf8
character_set_database  latin1
character_set_filesystem    binary
character_set_results   utf8
character_set_server    latin1
character_set_system    utf8
character_sets_dir  /opt/lampp/share/mysql/charsets/

通过我的PHP脚本运行相同的查询(附带print_r),输出如下:

Array
(
    [0] => Array
        (
            [Variable_name] => character_set_client
            [0] => character_set_client
            [Value] => latin1
            [1] => latin1
        )

    [1] => Array
        (
            [Variable_name] => character_set_connection
            [0] => character_set_connection
            [Value] => latin1
            [1] => latin1
        )

    [2] => Array
        (
            [Variable_name] => character_set_database
            [0] => character_set_database
            [Value] => latin1
            [1] => latin1
        )

    [3] => Array
        (
            [Variable_name] => character_set_filesystem
            [0] => character_set_filesystem
            [Value] => binary
            [1] => binary
        )

    [4] => Array
        (
            [Variable_name] => character_set_results
            [0] => character_set_results
            [Value] => latin1
            [1] => latin1
        )

    [5] => Array
        (
            [Variable_name] => character_set_server
            [0] => character_set_server
            [Value] => latin1
            [1] => latin1
        )

    [6] => Array
        (
            [Variable_name] => character_set_system
            [0] => character_set_system
            [Value] => utf8
            [1] => utf8
        )

    [7] => Array
        (
            [Variable_name] => character_sets_dir
            [0] => character_sets_dir
            [Value] => /opt/lampp/share/mysql/charsets/
            [1] => /opt/lampp/share/mysql/charsets/
        )

)

运行中

SET NAMES 'utf8';
SET CHARACTER SET 'utf8';
SHOW VARIABLES LIKE '%character%'

输出一个空数组。

3个回答

18

非常重要的是要指定与输入相匹配的编码方式来使用htmlentities,就像你在最后一个示例中所做的那样,但在前三个示例中省略了这一点。

htmlentities($text,ENT_COMPAT,'utf-8');

关于与MySQL通信,你需要确保连接排序规则和字符集与要传输的数据匹配。你可以在配置文件中设置,也可以在运行时使用以下查询进行设置:

SET NAMES utf8;
SET CHARACTER SET utf8;

请确保表格、数据库和服务器的字符集都匹配。有一个设置是无法在运行时更改的,那就是服务器的字符集。您需要在配置文件中进行修改:

[mysqld]
character-set-server = utf8
default-character-set = utf8 
skip-character-set-client-handshake

在MySQL手册中了解更多关于字符集和校对规则


啊!注释不支持换行! - luiscubal
在这种情况下,我没有以root身份登录。但是,PhpMyAdmin没有列出任何“ SET”权限。而且,我已经为该用户设置了特定于数据库的权限。我应该查看哪个特定的权限? - luiscubal
忘掉我关于特权的话,它应该无论如何都可以工作。你确定排序查询失败了吗?尝试运行“SHOW VARIABLES LIKE'%character%';”,看看当前连接设置了哪个排序规则。 - Eran Galperin
很抱歉,我错过了你发布的结果是不同的这一点。是的,在你的 PHP 脚本中连接排序肯定没有正确设置。你确定你正在运行我告诉你的相同脚本中的查询吗? - Eran Galperin
听着,我不知道该告诉你什么。这是强制连接编码的标准做法,我已经在数十个系统上成功使用过了。 - Eran Galperin
显示剩余15条评论

7
晚期复兴。但是以下是一些额外的提示:
  1. 使用mysql_set_charset而不是SET xxx
  2. 确保您正在使用UTF-8编码保存文件(这经常被忽视)
  3. 设置标题:
    <?php header("Content-type: text/html; charset=utf-8"); ?>

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

  4. 如果您的Apache服务器配置包含具有不同编码的AddDefaultCharset指令,请向您的主机管理员大喊大叫。

抱歉,但这是一个开发服务器,我现在已经没有了。因此,我无法再次复制这个问题。 - luiscubal

1

我刚遇到了这个问题。我的整个网站内容都是用西班牙语编写的,包括所有特殊字符(áéíóúñ)和它们的大写字母版本。

在我的情况下,问题出在服务器字符集/排序规则不一致。其他所有设置都是utf8,但服务器字符集却是latin1。这导致数据库中输入的所有utf8数据以其原始编码形式显示,例如L í将等于带有波浪符号~的A...

我正在使用mysqli,并且为了解决这个问题,我使用了Anthony Accioly上面解释的方法(使用mysql_set_charset)。该方法有一个mysqli版本,这就是我使用的。

之后,我感到困惑。查看我的网站时仍然很混乱。当然,我不知道通过将那个latin1更改为utf8,我也会搞乱整个事物的字符编码/解码。因此,我使用了一个在线字符串编码器/解码器来修复我的表格数据。

我对所有内容数据进行了各种导出(您可以设置它们以获取更新查询,这将加快您的更新过程),并通过上述在线编码器/解码器运行了SQL输出,然后将修复后的查询复制粘贴到phpmyadmin SQL面板中...从而修复了我的编码错误。现在一切都应该是正常的,而且我能够再次处理有损搜索:Maria、maria、maría、mariá都将匹配maría、maria、Maria等。所有重音字符都会评估为其基本元音字符。史诗级胜利。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接