魔法__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 期间访问它。
但要明确这个解决方案:这是绝望的措施。首先尝试以序列化形式提供缺失的信息。