> Le 23 nov. 2023 à 08:56, Rowan Tommins <rowan.coll...@gmail.com> a écrit :
>
> On 23 November 2023 01:37:06 GMT, Claude Pache <claude.pa...@gmail.com> wrote:
>> What you describe in the last sentence is what was initially designed and
>> implemented by the RFC: https://wiki.php.net/rfc/typed_properties_v2
>> (section Overloaded Properties).
>>
>> However, it was later changed to the current semantics (unset() needed in
>> order to trigger __get()) in https://github.com/php/php-src/pull/4974
>
>
> Good find. So not only is it not specified this way in the RFC, it actually
> made it into a live release, then someone complained and we rushed out a more
> complicated version "to avoid WTF". That's really unfortunate.
>
> I'm not at all convinced by the argument in the linked bug report - whether
> you get an error or an unexpected call to __get, the solution is to assign a
> valid value to the property. And making the behaviour different after unset()
> just hides the user's problem, which is that they didn't expect to *ever*
> have a call to __get for that property.
>
> But I guess I'm 4 years too late to make that case.
>
Hi,
I think that the legitimacy of the current behaviour is not something to be
convinced by abstract reasoning like we are doing now (otherwise, it wouldn’t
probably have waited a live release to be implemented in a rush), but something
that can be understood only by considering the conflicting uses of __get(),
which leads to conflicting expectations, and how they managed to live together
despite a fundamental contradiction:
1. __get() is used to implement virtual properties (as mentioned in the linked
bug report). For this use case, access to a declared property should not call
__get() (whose implementation may be hidden away in a superclass).
2. __get() is used to implement lazy properties. For this use case, access to
an uninitialised (or unset, or undeclared) property should call __get().
The two expectations did live together as long as declared properties were also
initialised (implicitly, to null). It is true that they are formally
incompatible; when you say:
> And making the behaviour different after unset() just hides the user's
> problem, which is that they didn't expect to *ever* have a call to __get for
> that property.
you are referring to the expectation given by use case 1, which contradicts the
expectation given by use case 2. However, it is not a problem in practice,
because users of classes implementing (1) but not (2) do not unset declared
properties, ever.
The conflict became evident with the advent of typed properties, which cannot
be implicitly initialised to null in general. As both use cases are firmly
rooted in practice, both should be taken in account. The current, cumbersome
and unfortunate behaviour allows to keep sane semantics for those classes using
bad practices (use case 1), while not invalidating naughty hacks used by other
classes (use case 2).
—Claude
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php