最近,我在尝试使用UTF-8以支持多种语言的站点时遇到了一些问题。基本上,您可以输入UTF-8字符——例如,带有变音符号的字符——但它们无法正确地传递到Web服务或数据库。经过更多调试后,我发现当我关闭站点上的javascript并使用可降级接口通过普通的旧HTTP提交表单时,一切正常——这意味着问题出在我们如何通过XHR发送数据上。
我们使用Prototype,特别是将数据POSTing回我们的站点—这意味着UI设计人员使用Form.serialize()
对传输数据进行编码。这反过来使用javascript函数encodeURIComponent()
来完成它的肮脏工作。
我在PHP中尝试了很多东西来将其解码为UTF-8,然后偶然发现了一个用Perl编写的解决方案。基本上,该解决方案使用正则表达式从字符串中获取urlencoded的十六进制值,然后进行双重转换关于值,先到十进制再到一个字符。PHP版本如下所示:
$value = preg_replace('/%([0-9a-f]{2})/ie', \"chr(hexdec('\1'))\", $value);
我们的代码中有一个方法来检测传入请求是否通过XHR。在那个逻辑中,一旦检测到XHR,我就会通过以下函数传递$_POST
:
function utf8Urldecode($value) { if (is_array($value)) { foreach ($key => $val) { $value[$key] = utf8Urldecode($val); } } else { $value = preg_replace('/%([0-9a-f]{2})/ie', 'chr(hexdec($1))', (string) $value); } return $value; }
这会将$_POST
数组中的所有UTF-8urlencoded值转换回UTF-8,然后我们可以继续正常处理。
伙计,但我等不及PHP6出来并修复这些unicode问题了……