Hi
On 7/17/25 18:26, Larry Garfield wrote:
Given the lack of consensus both here and in off-list discussions on how to
handle get hooks, we have done the following:
* Split the RFC into two sections, one for get, one for set.
* Expanded and refined the examples for both. The implementation is still the
original, however.
* Split the vote into two: one for allowing readonly get hooks, one for
readonly set hooks.
We will start the vote sometime this weekend, most likely, unless some major
feedback appears before then, and let the chips fall where they may.
After working through (most of) the discussion, I've now taken a look at
the updated RFC. I have the following remarks:
1.
It is really “write-once”, which is not the same as immutable (as shown above).
But there's no reason that “write-once” need be incompatible with hooks.
This is a strawman argumentation, as I've outlined in my previous
emails, calling readonly "write-once" is wrong. It is a reasonable user
expectation to always get the identical value when reading a value that
may only be set once. By calling it "write-once" you are trying to shift
the focus to the write operation, which is totally irrelevant for user
expectations when interacting with readonly properties. Especially for
expectations of users that just *use* a class rather than writing one.
2.
The concern would only appear if someone is deliberately doing something
non-stable
Or if someone accidentally calls a (deep) function chain that is non-pure.
3.
Or, for a more real-world and larger example, PHP 8.4 requires this:
This is false. You are perfectly able to write this in PHP 8.4:
final readonly class Entry
{
public readonly $terms;
public function __construct(
public string $word,
public string $slug,
array $terms,
) {
$this->terms = $this->upcastTerms($terms);
}
private function upcastTerms(array $terms): array
{
$upcast = static fn (Term|array $term): Term
=> $term instanceof Term ? $term : new Term(...$term);
return array_map($upcast, $value)
}
}
In no way do you need to use a property hook.
4.
// New code in 8.5:
$p = new PositivePoint(3, 4);
$p2 = clone($p, ['x' => -10]);
This is not legal code in PHP 8.5. Clone-with respects visibility and
since your asymmetric visibility RFC included the change, you are
probably aware that `readonly` implies `protected(set)`.
5.
but are now necessary to ensure that invariants are enforced.
And therefore with PHP 8.5 hooks are not necessary to enforce
invariants, except in the rare case where a `public(set) readonly`
property is used.
6.
So no guarantees are softened by this RFC.
Yes, they are. Unless `__get()` is implemented on a class (which is
explicitly visible as part of the public API), readonly guarantees the
immutability of identity.
7.
While that is an interesting idea that has been floated a few times, it has
enough complexities and edge cases of its own to address that we feel it is out
of scope.
While it certainly is your right as the RFC authors to consider certain
things out of scope for an RFC, I strongly oppose the notion of shipping
something that is strictly inferior and comes with obvious semantic
issues due to perceived complexity of another solution and then
following up with the proper solution that has already been identified.
As I've outlined in my previous emails, I found defining semantics for
an 'init' hook straight-forward when looking at how PHP works as of today.
8.
However, this RFC is in no way incompatible with adding an init hook in the
future should it be proposed.
This is true, but as I've mentioned before, an 'init' hook would enable
the same use cases without bringing along issues. So it really should be
"one of them, but not both" (with "one of them" being the init hook).
--------
After reading through the discussion, it seems the only argument against
the 'init' hook is perceived complexity. It is not at all clear to me
why this means that we must now rush something with clear issues into
PHP 8.5.
Best regards
Tim Düsterhus