(Edited this question, the old version quoted the wrong version of the RFC.)
The RFC for typed properties in PHP says that “If a typed property is unset()
, then it returns to the uninitialized state.” However, in PHP 7.4 (at least up to 7.4.5), it does appear to behave differently when the class implements __set()
, and thus it’s not exactly like the (original) uninitialized state. The magic function is not called when the uninitialized property is set for the first time, but it is (unexpectedly) called when the property is set again after having been unset. Example code.
<?php
class X {
public int $y;
public function __set($name, $value) {
echo "__set($name, $value) called";
$this->$name = $value;
}
}
$x = new X();
$x->y = 42; // Prints nothing, as expected.
unset($x->y);
$x->y = 43; // Prints `__set(y, 43) called`.
Am I overlooking something? Is this a bug in how PHP currently implements unset()
for typed properties? Or should __set()
even be called when an uninitialized typed property is set for the first time?
2
Answers
Magic getters/setters only trigger for non existing properties. Quote: https://www.php.net/manual/en/language.oop5.overloading.php#object.set ->
__set() is run when writing data to inaccessible (protected or private) or non-existing properties.
.So in your example, at first the public variables does exist. After unset, the public variable does not exist/unintialized and magic getter/setter come into place.
I think this behaviour is still wrong because the property exist but it is uninitialized. Should be maybe a bug report?
Why?
For the purpose of lazy initialization patterns.
So in PHP 8 they may forbid unsetting of declared properties, after providing some alternative mechanism for lazy initialization.