PHP URL解码/UTF8编码字符集与特殊字符的问题

3

我需要将一个英镑符号£传递给一个PHP页面,但是在ASP中进行了URL编码,变成了%C2%A3

问题:

urldecode("%C2%A3") // £
ord(urldecode("%C2%A3")) // get the character number - 194
ord("£") // 163  - somethings gone wrong, they should match

这意味着当我执行 utf8_encode(urldecode("%C2%A3")) 时,我得到的结果是 £

然而,执行 utf8_encode("£") 时,我得到了预期的结果 £

我该如何解决这个问题?

4个回答

3

如果你尝试过

var_dump(urldecode("%C2%A3"));

你会看到

string(2) "£"

因为这是2字节字符,ord()函数返回的是第一个字符的值(194 = Â)


为什么ord("£")返回163?如果我硬编码输入"£",我的代码的其余部分都可以正常工作,因此我希望PHP将其识别为char 163。 - Marcus
因为你自己打的。 - Arkh
@Arkh,那并不是很有帮助,因为我想让PHP将POST的变量“£”识别为char 163。 - Marcus
@Igor K - PHP将£识别为163(十六进制:A3),这是正确的,但您得到了194,因为在A3之前有C2,而194=C2...请看上面的String(2),但您只看到了"£",第一个字符不可见但仍然存在。在UTF-8中,您将看到£而不是£,这就是区别。 - Wh1T3h4Ck5

3

我认为ord()不支持多字节编码。它可能只返回字符串中第一个字符的代码,这是Â。在调用ord()之前尝试对字符串进行utf8_decode()处理,看是否有帮助。

ord(utf8_decode(urldecode("%C2%A3"))); // This returns 163

谢谢,这解决了我的问题,我在 $_POST["myvar"] 周围包裹了 utf8_decode(),现在一切都按预期工作。 - Marcus

2

太好了!那似乎描述了问题。 - Marcus
这并不是 PHP 中的问题或错误。该注释指的是客户端编码错误,可能是由于缺少 UTF8 元标签/头而发生的。如果您尝试修复此类错误请求,则会得到意外的结果。 - Phil

-1

php.net 上关于 urlencode() 的第一条评论解释了这个问题并建议使用以下代码来修复它:

<?php
function to_utf8( $string ) {
// From http://w3.org/International/questions/qa-forms-utf-8.html
    if ( preg_match('%^(?:
      [\x09\x0A\x0D\x20-\x7E]            # ASCII
    | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
    | \xE0[\xA0-\xBF][\x80-\xBF]         # excluding overlongs
    | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
    | \xED[\x80-\x9F][\x80-\xBF]         # excluding surrogates
    | \xF0[\x90-\xBF][\x80-\xBF]{2}      # planes 1-3
    | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
    | \xF4[\x80-\x8F][\x80-\xBF]{2}      # plane 16
)*$%xs', $string) ) {
        return $string;
    } else {
        return iconv( 'CP1252', 'UTF-8', $string);
    }
}
?> 

同时,您应该决定您想要发送到浏览器的最终HTML是UTF-8还是其他编码方式,否则您将继续在代码中出现£字符。


数据正在传递到一个内置的 PHP 类中,该类期望使用 UTF-8 编码。您是否看到使用该函数而不是 utf8_decode() 的任何理由? - Marcus
因为%C2%A3不是utf-8格式,所以utf-8-pund会变成%20%A4。你从ASP代码中获取的是iso-8859-1字符。 这个函数检查一个字符串是否有效的utf-8格式,如果不是就转换成utf-8格式。同时,使用utf8_decode()会得到iso-8859-1字符而非utf-8字符。 - Dexter
这个函数只是猜测编码,并在找不到任何utf8字符时执行utf8_encode。如果您在源头解决问题,就永远不需要像这样的东西。 - Phil

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