On Fri, Mar 31, 2023, at 8:56 AM, Robert Landers wrote:
> Hello,
>
> I couldn't find the thread about Property Hooks
> (https://wiki.php.net/rfc/property-hooks) -- I think it got embedded
> in various places? Or maybe my search-fu in gmail is failing me.
>
> Anyway, I was reading it carefully and I had a couple of questions.
>
> What would happen with the following class:
>
> class BigNumbers {
>   public \Gmp $myNumber {
>     beforeSet(int|string $value) {
>       return gmp_init($value);
>     }
>   }
> }
>
> Would $bigNumber->myNumber = gmp_init('25') throw an error because it
> isn't a `string|int`? Can hooks only accept the type they are setting
> or any type?
>
> In other words, will it be possible for this to no longer be true (I'm
> not sure it is always true now, fwiw):
>
> $x = $y = $z = 1;
>
> $x === $y && $y === $z;
>
> This looks like a very powerful change to the language and I'm really
> looking forward to using it!

As Rowan said, this is a "known unknown" at the moment, and one of the reasons 
the RFC hasn't been officially put forward yet.  (Expect that soon.)  

As it is right now, the value beforeSet receives MUST be the same as the 
property is typed as.  You're not allowed to declare a type yourself; the 
property type is implied.  However, that still would allow you to narrow a type 
yourself in practice.  The RFC has an example or two of that with strings -> 
UString objects.

We are considering (and I would favor, if it can be done cleanly) allowing the 
beforeSet hook to accept a contravariant (wider) type than the property type, 
but still be required to return exactly the type of the property.  That would 
allow, for instance:

class Foo {
  public int $val { beforeSet(int|string $new) => (int) $new; }
}

That is, you can accept a wider set of compatible types and then, in beforeSet, 
fold that down to the type of the property.  The type of the property is still 
guaranteed to be the only thing you get on read.

That would mean the following as a side effect:

$f = new Foo();
$val = '5';
$f->val = $val;
$f->val === $val; // false, because different types!

Personally I think that's acceptable for the flexibility it gives; the point of 
hooks is primarily to be "a thing you can add to a property in the future 
without having to precreate a method just in case", you can already do the 
above behavior with a method quite easily.  So being able to do the same with 
hooks (and thus obviate another "just in case" reason to add a verbose but 
pointless method on the off chance you need it in the future) seems reasonable.

There might be other edge cases we haven't thought of yet; right now that 
feature is pending on Ilija making sure it could even work, which is a 
prerequisite for including it, obviously. :-)

--Larry Garfield

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to