我有一个有这种定义的课程:
class AClass {
private $member;
}
我在不同的页面中对此类进行序列化和反序列化,并且工作正常。
现在由于某些原因,我不得不将类定义更改为:
class AClass {
public $member;
}
现在,当反序列化时,我得到一个null $ member值而不是存储在serialize字符串中的值。
很难给出一个有效的例子,因为这需要两个执行周期,但可以这样合成:https://3v4l.org/eTp6j。
解决此问题的最佳方法是什么?我现在唯一想到的就是编辑序列化的字符串,这似乎是一个草率的黑客。
由于
答案 0 :(得分:0)
你不能只改变类定义,希望一切都会好起来的。
当成员私有序列化字符串如下所示:
string(53) "O:5:"ATest":1:{s:13:"ATestmember";s:9:"something";}"
当成员公开时 - 序列化字符串为:
string(45) "O:5:"ATest":1:{s:6:"member";s:9:"something";}"
这就是您获得null
的原因 - 您无法从外部访问私人会员。
解决方案是更新数据库中的序列化字符串 - 通过从字段定义中删除ATest
类名称部分。
答案 1 :(得分:0)
我最终更改了数据库中的序列化字符串,但我必须知道哪些类的属性访问级别已更改。您可以批量为整个数据库执行此操作,但是当我们在一段时间后转储旧结果时,我已选择即时修改序列化字符串。
<?php
function newUnserializeFunction($response)
{
// Edit string
$classes = [
ATest::class
];
foreach ($classes as $class) {
do {
// Private class name
$result = replaceClassPrivateProtectedToPublic("\0" . $class . "\0", $response);
} while ($result);
do {
// Protected class name
$result = replaceClassPrivateProtectedToPublic("\0*\0" . $class . "\0*\0", $response);
} while ($result);
}
// Unserialize
$return = \unserialize($response);
return $return;
}
function replaceClassPrivateProtectedToPublic($className, &$content)
{
$classNameWithSlashes = preg_quote($className, '/');
$result = preg_match('/(([\d]+)\:\"' . $classNameWithSlashes . '([a-zA-Z0-9_]+))/', $content, $matches, PREG_OFFSET_CAPTURE);
if($result && count($matches) >= 4) {
$lengthOffset = $matches[2][1];
$lengthLength = strlen($matches[2][0]);
$length = strlen($matches[3][0]);
// Replace the class name
$content = preg_replace('/'.$classNameWithSlashes.'/', '', $content, 1);
// Replace the class name length
$content = substr_replace($content, $length, $lengthOffset, $lengthLength);
}
return $result;
}