10

我最近从 apt-get 在我的 Ubuntu 12.10 上安装了 PHP 5.4。

PHP Info 显示:PHP 版本 5.4.6-1ubuntu1

我只是安装了所有常见的包,如 mysql、pgsql、curl 等,没有进行任何其他更改,但我遇到了问题。

我喜欢在我的文件和数据库中使用 ISO-8859-1/latin1 编码,因为这是我获得最佳工作流程的地方。现在我遇到了一个问题,因为 PHP 似乎无法处理消息以这种方式编码的异常。

好吧,为了更好地澄清它,我创建了一个这样的测试文件:

ini_set('display_errors', 1);
error_reporting(E_ALL);

throw new Exception('é');

如果上面的代码在一个 utf-8 文件中,那就没问题了,启用 Xdegub 我得到:

( ! ) Fatal error: Uncaught exception 'Exception' with message 'é' in /home/henrique/public/teste.php on line 5
( ! ) Exception: é in /home/henrique/public/teste.php on line 5
Call Stack
#   Time    Memory  Function    Location
1   0.0002  124212  {main}( )   ../teste.php:0

如果文件在 ISO-8859-1 中,如果启用了 Xdebug,问题只是没有显示消息:

( ! ) Fatal error: in /home/henrique/public/teste.php on line 5
( ! ) Exception: in /home/henrique/public/teste.php on line 5
Call Stack
#   Time    Memory  Function    Location
1   0.0002  124436  {main}( )   ../teste.php:0

但是,如果没有 Xdebug,我得到的只是这个“非常清楚”的消息:

Fatal error: in /home/henrique/public/teste.php on line 5

也许这是 Apache 中的一个问题,因为当我使用命令行尝试相同的操作时,我得到:

Stack trace:
#0 {main}
  thrown in /home/henrique/public/teste.php on line 5

Fatal error: Uncaught exception 'Exception' with message '�' in /home/henrique/public/teste.php on line 5

Exception: � in /home/henrique/public/teste.php on line 5

Call Stack:
    0.0002     121256   1. {main}() /home/henrique/public/teste.php:0

该消息仍然存在,但是,难以辨认,但是是否存在...

编辑

我也尝试过使用 Lighttpd 1.4.28,结果是一样的。

编辑2:

尝试使用 PHP 5.4 内置服务器并在我的终端上得到了这个:

[Wed Jun  5 21:32:08 2013] PHP Fatal error:  Uncaught exception 'Exception' with message '�' in /var/www/test2.php:9
Stack trace:
#0 {main}
  thrown in /var/www/test2.php on line 9
[Wed Jun  5 21:32:08 2013] 127.0.0.1:55116 [200]: /test2.php - Uncaught exception 'Exception' with message '�' in /var/www/test2.php:9
Stack trace:
#0 {main}
  thrown in /var/www/test2.php on line 9

但是在浏览器中,还是同样的问题。

4

4 回答 4

1

PHP 中的异常消息是一个字符串,就像你没有消息一样。

PHP 中的字符串是二进制的。这实际上意味着 PHP 根本不关心其中的编码,PHP 中的字符串只保留任何可以用八位字节二进制数据表示的编码(即 8 位形成一个字节,然后是 PHP 字符串中的一个字符如果您使用子字符串访问(例如$string[10]访问第 11 个字符)。

因为所有这些都确保了无论您如何编写消息,它都会被传递到输出中。

所以唯一的区别是你如何显示输出。假设您在该异常消息字符串中获得了 Latin-1 编码,并通过您的 apache 服务器将其输出,然后您在浏览器中查看它,您的浏览器(到目前为止我们不关心原因)将其显示为UTF-8 你会看到问号-diagmond/水晶:�。

如果终端将其显示为 UTF-8,则同样适用于终端。

或者,如果您将输出保存到文件中,然后在编辑器中将该文件打开为 UTF-8 编码。

那么如何解决呢?对于您的浏览器,请查看您的浏览器文档,如何告诉您的浏览器您当前正在查看的网站应该以哪种编码显示。我知道的每个浏览器都有某种菜单,您可以在其中指定它。您使用的字符集很常见,因此即使是较旧的浏览器也有。

同样适用于终端。您可以设置 shell 的语言环境以及终端的编码。请查阅您正在使用的 shell 的文档。

对于文本文件,我敢打赌您现在已经知道如何处理它:检查您的编辑器提供的选项。


最后要注意的一点:如果您想正确分析服务器返回到包含异常消息输出的请求的内容,则需要使用浏览器的开发人员工具使服务器的响应标头可见。您可能会看到对先前配置的更改(错误地)说内容是 UTF-8 编码而编码是 latin-1。如果您不想手动更改浏览器中的编码,请修复该错误。为此,请查阅 PHP 文档和您的网络服务器的文档。

于 2013-07-18T11:00:48.007 回答
1

ab@php.net 给出了一个解释:

https://bugs.php.net/bug.php?id=63426&edit=2

无法修复的原因很复杂很简单。从 5.4 开始,PHP 的内部编码是 UTF-8,之前是 latin1。其他一切几乎没有变化。

在 HTML 上下文中显示的每条错误消息都需要转换实体。为此,使用了与 htmlspecialchars() 中相同的功能。在 PHP 5.4 之前它被迫使用 latin1,现在它被迫使用 UTF8。每个设计都有。将 header() 与 content-type 或 default_charset 一起使用仅影响 content-type 标头的发送。

因此,您在 latin1 中使用错误文本,但 UTF-8 将用于转换实体,并且会在第一个无效字符处消失。代码中的相关地方:http: //lxr.php.net/xref/PHP_5_4/main/main.c#1083,随后确定字符集()将为转换字符集提供 UTF8。这就是您的口音字符被吞下的原因。这就是为什么 Hui 无法重现这一点的原因 - 如果您之前查看他的帖子,确实 latin1 是以 content-type 发送的,但显然使用的是 UTF-8 编码的 PHP 脚本,因此错误消息是“致命错误:未捕获异常 'Exception' 带有消息 'é' in ..."。但是,当前条件并不强制您使用 UTF-8 编写脚本,在以拉丁文编码的脚本中,您仍然可以使用 utf8_encode('é') 引发异常。它与 CLI 一起工作的原因是因为不需要对 HTML 实体进行编码,因此字符按原样传递到输出。

这一切实际上意味着这个问题一直存在,但它有利于使用默认 iso-8859-1 的用户。现在使用默认 UTF-8 的用户可以获利。查看代码来解决这个问题可能需要比这张票要求更多的全局入侵。

对于 htmlspecialchars() 行为更改,另请参阅错误 #61354

于 2013-08-04T14:46:30.990 回答
1

您是否在其他服务器上尝试过此操作?

我认为是你的配置,我在我的服务器上创建了一个测试文件,你可以在这里查看它 http://cai.tlacaelelrl.com/tests/test.php

内容是

    ini_set('display_errors', 1);
    error_reporting(E_ALL);
    print 'Character encoding is: '.mb_internal_encoding();
    throw new Exception('é');

字符集应用于文件,我也将字符集添加到 htaccess 文件中。

我不确定这是否是因为 xdebug 但我无法在启用它的情况下进行测试。

你可以尝试添加这个

   AddCharset ISO-8859-1 .php

到您的 .htaccess 文件

于 2013-05-30T12:07:44.200 回答
0

我有同样的问题,但没有找到好的解决方案(.htaccess 中的“AddCharset ISO-8859-1 .php”不起作用)。你可以使用这个:

抛出新异常(htmlentities('é',ENT_COMPAT,'ISO-8859-1'));

但是 Xdebug 会显示:

à ;

总比没有好

于 2013-06-24T13:35:33.603 回答