编程语言
首页 > 编程语言> > php-将变量传递给__wakeup()

php-将变量传递给__wakeup()

作者:互联网

我正在数据库中存储某些对象.数据库中的每个节点都带有一个序列化的对象.节点可以有子级,因此对象也可以有子级.因此,我想用包含其直接子级的数组填充对象中的$children属性.当对象未序列化时,$children应该被填充.

为了避免从外部执行此操作,我认为我宁愿让对象自己执行此操作.但是,对象不知道它属于哪个数据库条目.因此,当调用__wakeup()时,对象缺少加载其自己的对应数据库条目所需的信息.

最好的办法是将一个变量传递给__wakeup(),尽管我知道unserialize()没有提供这种选择.

我找不到与此有关的任何信息.我将要得出结论,除了使用全局方法之外,这是不可能的,这不是我选择采用的途径.

可能吗?如果是,怎么办?

解决方法:

神奇的__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期间访问它.

只是要弄清楚这个解决方案:这是不顾一切的措施.首先,尝试使丢失的信息以序列化形式可用.

标签:magic-function,parameter-passing,php
来源: https://codeday.me/bug/20191121/2055734.html