On Fri, Jul 18, 2025, at 18:48, Eric Norris wrote: > On Fri, Jul 18, 2025 at 12:01 PM Rob Landers <rob@bottled.codes> wrote: > > > > > > > > On Fri, Jul 18, 2025, at 17:25, Tim Düsterhus wrote: > > > > Hi > > > > On 7/14/25 15:38, Larry Garfield wrote: > > > Thanks, Ilija. You expressed my concerns as well. And yes, in practice, > > > readonly classes over-reaching is the main use case; if you're marking > > > individual properties readonly, then just don't mark the one that has a > > > hook on it (use aviz if needed) and there's no issue. > > > > A readonly class is not just a convenience shortcut to mark each > > individual property as readonly. It has important semantics of its own, > > because it forces child classes to also be readonly. And even for final > > classes it communicates to the user that "I won't be adding non-readonly > > properties to the class". > > > > > > Wasn’t that the entire point of readonly classes? Because it was painful to > > write readonly for every property. Then if a property is readonly, the > > inherited property is also readonly, so, by extension: a class extending a > > readonly class is also readonly. > > > > There’s no “communication” here; just logic. > > > > > > Marking a class as readonly must therefore be a deliberate decision, > > since it affects the public API of your class and in turn also user > > expectations. > > > > > > Not really. I can remove the readonly designation and manually mark every > > property as readonly. The behavior of the class doesn’t magically change. > > Or, at least, I hope it doesn’t. > > > > > > > Perhaps we're thinking about this the wrong way, though? So far we've > > > talked as though readonly makes the property write-once. But... what if > > > we think of it as applying to the field, aka the backing value? > > > > I think of readonly from the view of the public API surface of an > > object. The property hooks RFC was very explicit in that property hooks > > are intended to be “transparent to the user” and can be added without > > breaking the public API. In other words: Whether or not a property is > > implemented using a hook should be considered an implementation detail > > and as a user of a class I do not care whether there is a backing value > > or not. > > > > > So readonly doesn't limit calling the get hook, or even the set hook, > > > multiple times. Only writing to the actual value in the object table. > > > That gives the exact same set of guarantees that a getX()/setX() method > > > would give. The methods can be called any number of times, but the > > > stored value can only be written once. > > > > As a user of a class the "backing table" is mostly inaccessible to me > > when interacting with objects. It's only exposed via var_dump() and > > serialize(), the former of which is a debug functionality and the output > > of latter not something I must touch. > > > > > It would not guarantee $foo->bar === $foo->bar in all cases (though that > > > would likely hold in the 99% case in practice), but then, $foo->getBar() > > > === $foo->getBar() has never been guaranteed either. > > > > Properties and methods are something different. For methods there a > > reasonable expectation that *behavior* is associated with them, for > > properties there is not. > > > > > > Unless I missed something. Hooks are fancy methods? There is nothing > > intrinsic about object properties. There is nothing that says two calls to > > the same property’s getters are going to result in the same values. There > > is asynchronous php, declare ticks, etc. especially in the case of globals, > > there is no guarantee you even have the same object. At the end of the day, > > it is up to the programmer building that system / program to provide those > > guarantees— not the language. > > I do think that, without any additional information, it would be > reasonable to assume that `$foo->bar === $foo->bar`, i.e. there would > not be side-effects until you've called a method or written to the > object in some way. So I share Tim's opinion here, but I do agree that > with hooks available this is not actually a guarantee. You could > certainly have a `$foo->random_value` property and document that it > will be different each time you call it. > > That said, once the programmer has added the readonly designation to a > property, I do think that something says that two calls to the same > property will result in the same values - the readonly designation. I > disagree with the point that it's not up to the language - the > language should provide an affordance for enforcing programmer intent, > and I see no reason to even have a readonly designation if we're going > to make it easily circumventable or otherwise just a "hint". > > It seems that one common counterpoint to the "let's not make it > circumventable" argument is to point out that it's already > circumventable via __get. I agree with Claude that this is not a > justification for making it *easier* to circumvent. I would also like > to note that the original RFC > (https://wiki.php.net/rfc/readonly_properties_v2#unset) seems to allow > this behavior *for the purpose of lazy initialization*. With an `init` > hook, we'd have solved this problem, and could deprecate the `__get` > hack for `readonly` properties / classes. > > Nicolas Grekas said "__get is certainly not legacy; removing it would > break many use cases without proper alternatives.", but note that I'm > only suggesting we could maybe deprecate __get for `readonly` > properties once we had an `init` hook - I'm not proposing deprecating > it generally. Without a counterexample, I don't think there would be > another reason for `__get` to work with `readonly` properties. >
I personally feel that making special restrictions and affordances to readonly classes is a bad language design. It is a “class” and not something special or different like an enum. This is just a class with its properties made readonly. The word says it all — read. Only. Personally, I don’t use readonly much any more. The amount of restrictions and weird behavior just makes it impossible for any real-world use except for narrow cases the original authors of the feature dreamed up. With hooks and asymmetrical viz, it’s nearly an obsolete feature anyway. — Rob