> On 1 Dec 2022, at 08:38, Stephen Reay <php-li...@koalephant.com> wrote:
>
>
>
>> On 30 Nov 2022, at 22:09, Larry Garfield <la...@garfieldtech.com> wrote:
>>
>> On Tue, Nov 29, 2022, at 11:25 PM, Stephen Reay wrote:
>>
>>> Hi Larry,
>>>
>>> Thank you for clarifying the setter behaviour in more explicit terms,
>>> but I have to say I’m quite disappointed in this continued “use the
>>> logic of readonly to apply to something that is explicitly not
>>> readonly” - this is even more stark now that you’ve explicitly made
>>> them mutually exclusive behaviours.
>>>
>>> I’m generally very in favour of maintaining consistency, but this seems
>>> like it’s using technical consistency as an excuse to justify
>>> unintuitive behaviour that breaks consistency in another, much more
>>> obvious way.
>>>
>>>
>>> Can you explain why it makes more sense to maintain consistency with
>>> “readonly” than it does to maintain consistency with the existing
>>> “__set()” behaviour for properties, particularly now that you’ve
>>> indicated these features (asymmetric visibility and readonly) are
>>> mutually exclusive?
>>>
>>> While it’s stated multiple times that “readonly” introduced a limited
>>> form of asymmetric visibility, and thus this is a continuation, in
>>> terms of intuitiveness, the existing __set() rules are very easy to
>>> comprehend even with readonly:
>>>
>>> - if the property is declared as public, __set() is never called; if
>>> it’s declared as protected, __set is called when the property is
>>> accessed from outside that class or it’s hierarchy. Yes, I know that
>>> readonly imposes an implicit visibility difference - but that is
>>> essentially an implementation detail, from the point of view of the
>>> userland developer, it’s not a clear statement of intended behaviour on
>>> their part, expressed through the code as written.
>>>
>>> For example, with `public readonly int $foo` it’s quite obvious why
>>> __set() isn’t called, using the exiting well-understood logic: it’s a
>>> public property. PHP applies a kind of asymmetric visibility to the
>>> property behind the scenes, but that isn’t what the developer declared,
>>> it’s the implementation. This behaviour matches that of regular,
>>> non-readonly fields: when the field is declared public (or has implicit
>>> public visibility) __set() is never called.
>>>
>>> If we make that field protected, __set() will be called when the
>>> property is written to from outside the class, regardless of whether
>>> it’s readonly or not.
>>>
>>>
>>> What you’re proposing changes that, in a way that is completely
>>> unintuitive: when attempting to *write* data to a property that is
>>> marked as protected(set), the __set() method will not be called.
>>>
>>>
>>> So please, can you explain to me why consistency with an implementation
>>> detail of readonly properties is more important than consistency with
>>> declared developer intention for regular properties via the magic
>>> setter method?
>>
>> There's a couple of reasons.
>>
>> One, and arguably the most important, readonly and aviz being incompatible
>> is, hopefully, a temporary situation. There's some fiddly bits to work out
>> design-wise, and based on earlier comments in the thread we're going to punt
>> on that for now to avoid that dragging down the whole RFC. I believe we
>> absolutely should allow them together in the future (maybe in a later 8.3
>> RFC, maybe a future version, TBD), which means ensuring, now, that they are
>> compatible in the future. This approach involves the fewest future BC
>> breaks.
>>
>> Second, I wouldn't call the current behavior of readonly a mere
>> implementation detail. It's weird and unexpected, I'd agree, but only as a
>> side effect of previous design decisions, some of which are even older than
>> readonly. But it's an observed behavior that code can rely on, and in some
>> cases does. For example:
>>
>> https://peakd.com/hive-168588/@crell/php-tricks-lazy-public-readonly-properties
>>
>> The "unset a declared property to force it through __get once" is a trick
>> that some ORMs use extensively. readonly just inherited that, leading to
>> the current behavior: __set depends on the write/set visibility of the
>> property and its settedness. This RFC doesn't change anything there.
>>
>> The alternative would be to have __set called always for a non-public-set
>> property. However, that is a place for bugs, as you then can't not have a
>> back-door way to publicly set a property even if it's declared private(set).
>> (Or, you have to be very careful in your __set to avoid it.) That is both
>> inconsistent with the language today, and error prone.
>>
>> Finally, we're planning to work in the near-future on property hooks (aka
>> property accessors), which would allow per-property custom set routines.
>> That would largely remove the issue entirely, as the use of __set would go
>> way down and you'd basically never have to use it with a declared property,
>> fancy tricks or no, so this issue would never come up at all.
>>
>> --Larry Garfield
>>
>> --
>> PHP Internals - PHP Runtime Development Mailing List
>> To unsubscribe, visit: https://www.php.net/unsub.php
>
> Hi Larry,
>
>
> I think there must be some confusion somewhere, based on some of your
> comments.
>
> I’m not suggesting that the “unset to force a **public** property to go
> through getter/setter methods” logic should be specifically different.
>
> I’m suggesting that when the decision is made to call __set or not, the
> properties **set** visibility is what should be considered, not it’s **get**
> visibility.
>
> Your own comment even describes this behaviour: "leading to the current
> behavior: __set depends on the write/set visibility of the property"
>
> But your RFC says that __set will depend on the **read/get** visibility of
> the property.
>
>
>> you then can't not have a back-door way to publicly set a property even if
>> it's declared private(set). (Or, you have to be very careful in your __set
>> to avoid it.) That is both inconsistent with the language today, and error
>> prone.
>
> If a developer adds a _set() method that can write to a private(set)
> property, I would expect that is working exactly as desired, exactly as it
> does **now** where it’s just a “protected” property.
>
>
>> we're planning to work in the near-future on property hooks
>
> That’s great, but I don’t think weird unintuitive behaviour should be added
> because “well we’re gonna try and solve this through something else later”
>
>
>
> Cheers
>
> Stephen
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: https://www.php.net/unsub.php
>
Apologies, I meant “where it’s just a private property” rather than “just a
protected property” in the second to last sentence.
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php