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 |1 Answer
Reset to default 1No 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)
serialize
/unserialize
are said to operate with the "raw" value there, bypassing the hooks. – C3roe Commented Feb 3 at 10:48__sleep()
– Eran Machiels Commented Feb 3 at 11:39__sleep
method returns['foo', 'bar']
- and therefor it also looks for a propertybar
, when you unserialize this again. Butunserialize
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