最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

php - Property hook not found when serializing an object using __sleep - Stack Overflow

programmeradmin0浏览0评论

I noticed something strange when using the combination property hooks with the magic __sleep() method. I have no idea whether I incorrectly use hooks or that this is a bug in PHP.

See the following example:

class A {
    private array $foo = ['baz' => 10];

    public int $bar {
        get => $this->foo['baz'];
        set {
            $this->foo['baz'] = $value;
        }
    }
    
    public function __sleep()
    {
        // ...
        return array_keys(get_object_vars($this));
    }
}

$a = new A;
$a->bar = 20;

var_dump(unserialize(serialize($a)));

This causes the following warning:

serialize(): "bar" returned as member variable from __sleep() but does not exist

Which is strange, because it works as expected and the property does exist. Reproducable example: .4.3.

This is an issue because in the framework I use (Laravel), this warning is promoted to an exception and breaks my application.

I noticed something strange when using the combination property hooks with the magic __sleep() method. I have no idea whether I incorrectly use hooks or that this is a bug in PHP.

See the following example:

class A {
    private array $foo = ['baz' => 10];

    public int $bar {
        get => $this->foo['baz'];
        set {
            $this->foo['baz'] = $value;
        }
    }
    
    public function __sleep()
    {
        // ...
        return array_keys(get_object_vars($this));
    }
}

$a = new A;
$a->bar = 20;

var_dump(unserialize(serialize($a)));

This causes the following warning:

serialize(): "bar" returned as member variable from __sleep() but does not exist

Which is strange, because it works as expected and the property does exist. Reproducable example: https://3v4l./V1S5i#v8.4.3.

This is an issue because in the framework I use (Laravel), this warning is promoted to an exception and breaks my application.

Share Improve this question asked Feb 3 at 10:33 Eran MachielsEran Machiels 8812 gold badges9 silver badges19 bronze badges 3
  • Guessing that has to do with what is explained under "Serialization" here, php/manual/en/language.oop5.property-hooks.php - "The behavior of hooks [during serialization] varies depending on the use case. In some cases, the raw backing value of a property will be used, bypassing any hooks. In others, the property will be read or written "through" the hook, just like any other normal read/write action." - serialize / unserialize are said to operate with the "raw" value there, bypassing the hooks. – C3roe Commented Feb 3 at 10:48
  • Thanks for your answer @C3roe, using the raw value is fine. Note that without the sleep, all works as expected. But I noticed as well that when I set the property in my setter as well (instead of only setting the variable), the warning goes away: 3v4l./tlUP3#v8.4.3. But is weird that that only happens when using __sleep() – Eran Machiels Commented Feb 3 at 11:39
  • 1 Your __sleep method returns ['foo', 'bar'] - and therefor it also looks for a property bar, when you unserialize this again. But unserialize doesn't use the hooks. It would have to return ['foo'] only, then it would work without errors - 3v4l./qQ1s1#v8.4.3 – C3roe Commented Feb 3 at 11:46
Add a comment  | 

1 Answer 1

Reset to default 1

No idea how much nitpicking about the word "member" in the error message is necessary. The diagnostic message is likely a bit surprising indeed, but hooks are new, too. Reading __sleep() it may stem from the warning returning the member name of an inaccessible parents private property. But I've not looked into the source.

If a bug, then it should be possible to serialize the property. As analyzed in comments already, it's a virtual one, and therefore it makes not much sense to serialize it (so not/a bug).

Undocumented:

In your posted example, you can replace get_object_vars() with get_mangled_object_vars(). It silently discards uninitialized typed properties (documented) and virtual properties with hooks as it seems (just learned).

Demo


References

  • PHP: get_mangled_object_vars — Returns an array of mangled object properties - Manual (php)
  • PHP: __sleep() and __wakeup() Magic Methods - Manual (php)
发布评论

评论列表(0)

  1. 暂无评论