PHP 取消序列化是否因未编码字符而失败?

2022-08-30 14:01:45
$ser = 'a:2:{i:0;s:5:"héllö";i:1;s:5:"wörld";}'; // fails
$ser2 = 'a:2:{i:0;s:5:"hello";i:1;s:5:"world";}'; // works
$out = unserialize($ser);
$out2 = unserialize($ser2);
print_r($out);
print_r($out2);
echo "<hr>";

但是为什么?
我应该在序列化之前进行编码吗?如何?

我正在使用Javascript将序列化字符串写入隐藏字段,而不是PHP的$ _POST
在JS中,我有这样的东西:

function writeImgData() {
    var caption_arr = new Array();
    $('.album img').each(function(index) {
         caption_arr.push($(this).attr('alt'));
    });
    $("#hidden-field").attr("value", serializeArray(caption_arr));
};

答案 1

失败的原因有:unserialize()

$ser = 'a:2:{i:0;s:5:"héllö";i:1;s:5:"wörld";}';

是因为 和 的长度是错误的,因为 PHP 本身不能正确处理多字节字符串:héllöwörld

echo strlen('héllö'); // 7
echo strlen('wörld'); // 6

但是,如果您尝试以下正确的字符串:unserialize()

$ser = 'a:2:{i:0;s:7:"héllö";i:1;s:6:"wörld";}';

echo '<pre>';
print_r(unserialize($ser));
echo '</pre>';

它的工作原理:

Array
(
    [0] => héllö
    [1] => wörld
)

如果使用 PHP,它应该正确计算多字节字符串索引的长度。serialize()

另一方面,如果你想使用多种(编程)语言的序列化数据,你应该忘记它,改用像JSON这样的东西,它更加标准化。


答案 2

我知道这是一年前发布的,但我只是有这个问题并遇到这个问题,实际上我找到了解决方案。这段代码就像魅力一样!

背后的想法很简单。它只是通过重新计算上面@Alix发布的多字节字符串的长度来帮助您。

一些修改应该适合您的代码:

/**
 * Mulit-byte Unserialize
 *
 * UTF-8 will screw up a serialized string
 *
 * @access private
 * @param string
 * @return string
 */
function mb_unserialize($string) {
    $string = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $string);
    return unserialize($string);
}

资料来源:http://snippets.dzone.com/posts/show/6592

在我的机器上测试,它像魅力一样工作!


推荐