我将某些对象存储在数据库中。数据库中的每个节点都带有一个序列化对象。节点可以有子节点,因此,对象也可以有子节点。因此,我想用一个包含其直接子节点的数组填充对象中的$children
属性。 1>}在对象被反序列化时应该填充。
在试图避免从外部做这个时,我认为我宁愿让对象本身去做。但是,该对象不知道它属于哪个数据库条目。因此,当调用$children
时,该对象缺少加载其自己的相应数据库条目所需的信息。
看起来最好的是能够将变量传递给__wakeup()
,但我知道__wakeup()
没有提供此类选项。
我无法找到有关此事的任何信息。我即将得出结论,除了使用全局之外,它是不可能的,这不是我选择采用的路线。
有可能吗?如果是,怎么样?
答案 0 :(得分:3)
魔法__wakeup()
method does not allow passing of arguments。这里的想法是拥有对象所需的一切,以便将自身反序列化为已经序列化形式的有效状态,例如,它期望对象在序列化时处于有效状态。
这意味着,如果子项所属的数据库条目的信息丢失但对象必须处于有效状态,则应首先将其添加到对象中。然后,您可以在反序列化对象时简单地访问该值。这将是最干净的解决方案。
另一个选择是采用全局变量。我同意,没有人想要那个。
另一个同样令人怀疑和令人难以置信的神奇选择是在反序列化对象以添加缺少的信息之前弄乱序列化表单。
以下是概念证明:
function unserialize_with_args($string, array $args, $key = 'tmp')
{
// serialize $args to $key for inserting into $string
$tmps = sprintf(
's:%d:"%s";%s}',
strlen($key),
$key,
serialize($args)
);
// increase property count in original string
$string = preg_replace_callback(
'/^(O:\d+:"[a-z]+":)(\d+)/i',
function (array $matches) {
return $matches[1] . ($matches[2] + 1);
},
$string
);
// insert $tmps, unserialize, remove tmps
$instance = unserialize(substr_replace($string, $tmps, -1));
unset($instance->$key);
return $instance;
}
你可以这样做:
class Foo
{
public function __wakeup()
{
print_r($this->tmp);
}
}
unserialize_with_args(
serialize(new Foo),
[1,2,3]
);
运行该代码将打印(demo):
Array
(
[0] => 1
[1] => 2
[2] => 3
)
这是有效的,因为该函数将属性tmp
添加到序列化表单中,该表单包含作为$args
传递的序列化数组。因此,当对象被唤醒时,它将可以访问这些值。该函数将在返回反序列化对象之前删除该属性,因此您只能在__wakeup
期间访问它。
但是要明确这个解决方案:这是绝望的措施。首先尝试以序列化形式提供缺失的信息。