> 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

Reply via email to