-
Notifications
You must be signed in to change notification settings - Fork 7.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Property hooks do not call parent's magic __get
and __set
methods when referencing parent property
#17542
Comments
|
I agree. It's honestly not something that we explicitly considered, but I agree that |
Thanks for the quick response! The manual currently says (emphasis mine):
It also gives an example of referencing the parent's property (not hook): <?php
class Strings
{
public string $val;
}
class CaseFoldingStrings extends Strings
{
public bool $uppercase = true;
public string $val {
get => $this->uppercase
? strtoupper(parent::$val::get())
: strtolower(parent::$val::get());
}
}
?> So I don't see how this is parent-hook-specific, since you can access plain properties. And if you can access a plain property, you should be able to access a private or non-existent one via That said, if the workaround approach is preferred, I think at the least the error messaging could be changed. My mental model is that you won't see a |
Right. This sentence implies that the parent declares such a property, but without a hook for the given operation, in which case we'll resort to accessing the properties backing store. The idea of this fallback is to allow adding hooks to child properties in a backwards compatible way, i.e. by avoiding direct access of the backing value that would break if the parent were to add a hook itself (or more precisely, it would circumvent the parents hook). I don't think your expectation for this to work is unreasonable, but it wasn't documented, and thus is technically a language change. I personally don't think we need this fallback, and it might not be quite straight forward to implement. But if you feel strongly about this topic, feel free to ask for opinions on the internals mailing list.
Can you make a concrete suggestion? |
I can see where you're coming from, but to me it just implies "it will try to fetch the property normally", where normally means "it will follow the existing property access patterns", and hence why I'd expect
I don't think I feel too strongly, but yeah I might raise it there; I think it'd be nice to either be consistent, or more strongly indicate that this will only work for existing properties or hooks. On that note...
This is tough, because in a sense there is an "
..." I think I'd be satisfied with this, because we're calling out that this language construct ( |
Mm, yeah, we never really thought about this case. I would not be opposed to falling back to |
Just to clarify:
This section explicitly refers to a declared parent property. So, it's not really a matter of interpretation. However, the case where the parent property is not declared is unspecified. It should have been explicitly declared whether this will error, or calling magic methods. That said, I believe calling magic methods would also not be consistent, as accessing properties from the parent class will actually use the child property if declared there, rather than calling magic methods. E.g. https://3v4l.org/06HfX class P {
public function setProp() {
$this->prop = 'foo';
}
public function __set($name, $value) {
var_dump('__set', $name, $value);
}
}
class C extends P {
public $prop;
}
$c = new C();
$c->setProp();
var_dump($c); Furthermore, if the parent property does not contain magic get/set, does that mean we're resorting to dynamic properties? That's would inevitably clash with non-virtual child properties. Similarly, what happens with It's not obvious to me what the correct, consistent behavior is here. |
Description
I was playing around with property hooks and noticed the following (in my opinion) inconsistency when combining property hooks with inheritance and
__get
and__set
:The following code (for
__get
, the same applies for__set
in https://3v4l.org/Q2OAj):Resulted in this output:
But I expected this output instead:
I tried searching the RFC and existing PHP issues, but I haven't found this example - apologies if I missed it. Barring something saying that this shouldn't work, I would expect it to.
PHP Version
PHP 8.4.3
Operating System
No response
The text was updated successfully, but these errors were encountered: