魔术__wakeup()
方法不允许传递参数。这里的想法是拥有对象所需的一切,以便已经以序列化形式将自身反序列化为有效状态,例如,它期望对象在被序列化时处于有效状态。
这意味着,如果缺少子项所属的数据库条目的信息,但该信息是对象处于有效状态所必需的,则应首先将其添加到对象中。然后,您可以在反序列化对象时简单地访问该值。这将是最干净的解决方案。
另一种选择是求助于全局变量。我同意,没有人想要那样。
另一个同样令人怀疑和令人难以置信的神奇选择是在反序列化对象以添加丢失的信息之前弄乱序列化形式。
这是一个概念证明:
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]
);
运行该代码将打印(演示):
Array
(
[0] => 1
[1] => 2
[2] => 3
)
这是有效的,因为该函数tmp
向序列化表单添加了一个属性,该表单保存了作为传递的序列化数组$args
。因此,当对象被唤醒时,它将可以访问这些值。该函数将在返回未序列化的对象之前删除该属性,因此您只能在__wakeup
.
但要明确这个解决方案:这是绝望的措施。首先尝试以序列化形式提供缺失的信息。