Hi folks.  Based on earlier discussions, we've made a number of changes to the 
RFC that should address some of the concerns people raised.  We also had some 
very fruitful discussions off-list with several developers from the Foundation, 
which led to what we feel are some solid improvements.

https://wiki.php.net/rfc/property-hooks

Smaller changes:

1. We've added a PropertyHookType enum for use in reflection, which lets us get 
rid of a possible exception.
2. get_mangled_object_vars()'s behavior is now defined to be the same as an 
array, ie, skip hooks.
3. A final property with a final hook is no longer an error. It's just silently 
redundant, like for methods.
5. Made explict what happens with recursive hook calls and method calls from a 
hook.  The behavior here is the same as for __get/__set.
6. Made support for #[\Override] explicit.
7. Added an FAQ regarding the property-centric approach rather than 
method-centric approach.
8. Clarified that the parent::$foo::get() syntax works on a parent property 
regardless of whether it has hooks.
9. Clarified that untyped properties are supported.  (Though, it's 2024, please 
don't use untyped properties.)
10. Clarified that interface properties cannot specify a wider write-type, for 
simplicity.  That could be considered as a future add-on with no BC breaks.
11. Provided an explanation of how to interpret the parent-hook access syntax.
12. Added an FAQ item explaining why a 'virtual' keyword is not feasible.

Larger changes:

0. As noted a while ago, $field has been removed.

1. I've added an FAQ question regarding the parent::$foo::get() syntax, and why 
it is.

2. The $foo => expression shorthand has been removed.  The legal shorthands are 
now:

public string $foo {
  get => evaluates to a value;
  set => assigns this value;
}

3. The set shorthand (with => ) now means "write this value instead".  The 
non-shorthand version (set { } ) is always return void, so you have to assign 
the value yourself but you get more flexibility.  Having updated the examples 
accordingly, I think this is actually a really nice and intuitive trade-off, as 
it makes the common transformation and validation cases (eg, in constructor 
promotion) even easier to follow with no redundancy.

4. On a set hook, the user may specify both a type and name, or neither.  (That 
is, set {} or set (Foo $newFoo).  If not specified, it defaults to the type of 
the property and $value, as before.

5. I restructured how the content in 2, 3, 4 is presented and moved some stuff 
around so that it flows more logically (I think).

6. The restrictions around references have been softened.  Specifically, 
references are only disallowed if a backed property has a set hook.  If it has 
only a get, or if it's a virtual property, references are allowed.  We also 
added a future-scope section on a possible way to support assigning by 
reference in the future, if there is sufficient need.

7. Interfaces may now require a &get hook, or just 'get'.  A class may use a 
&get hook on a 'get' interface declaration.  This is the same logic as already 
exists for methods; we're just copying it.

Hopefully the above changes should resolve most outstanding concerns.  I do 
think the updated shorthand handling is better overall, so I'm happy with it.

There also seems to be little consensus so far on naming this thing hooks vs 
accessors.  Absent a consensus, we'll probably stick with hooks to avoid the 
effort of renaming all the things.

Thank you everyone for the feedback so far, and if you still have some, please 
say so.  (Even if it's just to say that you're happy with the RFC now so we 
feel more comfortable bringing it to a vote.)

--Larry Garfield

Reply via email to