【问题标题】:Passing a variable to __wakeup()将变量传递给 __wakeup()
【发布时间】:2014-04-30 13:44:42
【问题描述】:

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

在试图避免这样做从外部我想我宁愿让对象本身来做。但是,该对象不知道它属于哪个数据库条目。因此,当调用__wakeup() 时,对象缺少加载其自己的相应数据库条目所需的信息。

最好的办法是能够将变量传递给__wakeup(),尽管我知道unserialize() 不提供这样的选项。

我无法找到有关此的任何信息。我正要得出结论,这是不可能的,除了使用全局,这不是我选择采取的路线。

有可能吗?如果是,怎么做?

【问题讨论】:

    标签: php parameter-passing magic-function


    【解决方案1】:

    魔法__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 期间访问它。

    但要明确这个解决方案:这是绝望的措施。首先尝试以序列化形式提供缺失的信息。

    【讨论】:

    • 内容丰富!谢谢你。两种解决方法(全局变量和摆弄序列化数据)都不是我的选择,但你提供了这个例子真是太棒了!实际上,我应该将信息与对象一起存储。将databaseId 字段存储在我存储在数据库数据集中的对象中,感觉非常奇怪。也许这只是我不想玩的半颠倒完美主义。
    猜你喜欢
    • 1970-01-01
    • 2020-01-24
    • 2012-02-13
    • 2014-09-05
    • 2011-10-13
    • 2013-12-07
    • 2014-12-02
    • 2016-03-04
    • 2023-03-31
    相关资源
    最近更新 更多