Re: [PHP-DEV] [RFC] Property hooks, nee accessors
Hey everyone. Any news on this? I'm really excited about this one. =) -- Erick de Azevedo Lima Em ter., 30 de mai. de 2023 às 14:15, Larry Garfield escreveu: > > > -- > Larry Garfield > la...@garfieldtech.com > > On Mon, May 29, 2023, at 8:28 PM, Claude Pache wrote: > >> Le 8 mai 2023 à 23:38, Larry Garfield a écrit > : > >> > >> Ilija Tovilo and I would like to offer another RFC for your > consideration. It's been a while in coming, and we've evolved the design > quite a bit just in the last week so if you saw an earlier draft of it in > the past few months, I would encourage you to read it over again to make > sure we're all on the same page. I'm actually pretty happy with where it > ended up, even if it's not the original design. This approach eliminates > several hard-to-implement edge cases while still providing a lot of > functionality in one package. > >> > >> https://wiki.php.net/rfc/property-hooks > >> > > > > Hi, > > > > If I understand correctly, given: > > > > > > > class C { > > > > public int $someInt; > > > > public float $someFloat; > > > > public int $someIntWithHook { > > get => $field; > > set => $field = $value; > > } > > > > public float $someFloatWithHook { > > get => $field; > > set => $field = $value; > > } > > > > } > > ?> > > > > we have: > > > > > $obj = new C; > > var_dump($obj->someInt = 42.0); // int(42) > > var_dump($obj->someFloat = 42); // float(42) > > ?> > > > > but: > > > > > $obj = new C; > > var_dump($obj->someIntWithHook = 42.0); // float(42) > > var_dump($obj->someFloatWithHook = 42); // int(42) > > ?> > > > > If I am correct, it means that the “This also implies that adding a set > > hook to a property cannot change the result of the = operator” > > statement is a bit too optimistic. > > We looked into this a bit; it's correct if you're in weak mode. In strict > mode, it applies only to $o->float = $anInt, as that's the only legal type > coercion. Still, you're right that it's not quite "cannot change", so I've > adjusted the wording to better describe the edge cases. The behavior is > still the same as __set(), so we don't see a need to change it further. > > Thanks for the catch. > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
-- Larry Garfield la...@garfieldtech.com On Mon, May 29, 2023, at 8:28 PM, Claude Pache wrote: >> Le 8 mai 2023 à 23:38, Larry Garfield a écrit : >> >> Ilija Tovilo and I would like to offer another RFC for your consideration. >> It's been a while in coming, and we've evolved the design quite a bit just >> in the last week so if you saw an earlier draft of it in the past few >> months, I would encourage you to read it over again to make sure we're all >> on the same page. I'm actually pretty happy with where it ended up, even if >> it's not the original design. This approach eliminates several >> hard-to-implement edge cases while still providing a lot of functionality in >> one package. >> >> https://wiki.php.net/rfc/property-hooks >> > > Hi, > > If I understand correctly, given: > > > class C { > > public int $someInt; > > public float $someFloat; > > public int $someIntWithHook { > get => $field; > set => $field = $value; > } > > public float $someFloatWithHook { > get => $field; > set => $field = $value; > } > > } > ?> > > we have: > > $obj = new C; > var_dump($obj->someInt = 42.0); // int(42) > var_dump($obj->someFloat = 42); // float(42) > ?> > > but: > > $obj = new C; > var_dump($obj->someIntWithHook = 42.0); // float(42) > var_dump($obj->someFloatWithHook = 42); // int(42) > ?> > > If I am correct, it means that the “This also implies that adding a set > hook to a property cannot change the result of the = operator” > statement is a bit too optimistic. We looked into this a bit; it's correct if you're in weak mode. In strict mode, it applies only to $o->float = $anInt, as that's the only legal type coercion. Still, you're right that it's not quite "cannot change", so I've adjusted the wording to better describe the edge cases. The behavior is still the same as __set(), so we don't see a need to change it further. Thanks for the catch. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
> Le 8 mai 2023 à 23:38, Larry Garfield a écrit : > > Ilija Tovilo and I would like to offer another RFC for your consideration. > It's been a while in coming, and we've evolved the design quite a bit just in > the last week so if you saw an earlier draft of it in the past few months, I > would encourage you to read it over again to make sure we're all on the same > page. I'm actually pretty happy with where it ended up, even if it's not the > original design. This approach eliminates several hard-to-implement edge > cases while still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks > Hi, If I understand correctly, given: $field; set => $field = $value; } public float $someFloatWithHook { get => $field; set => $field = $value; } } ?> we have: someInt = 42.0); // int(42) var_dump($obj->someFloat = 42); // float(42) ?> but: someIntWithHook = 42.0); // float(42) var_dump($obj->someFloatWithHook = 42); // int(42) ?> If I am correct, it means that the “This also implies that adding a set hook to a property cannot change the result of the = operator” statement is a bit too optimistic. —Claude -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
I can't wait! Especially because I'm heading a modernization of the systems in my organization and my plan is to use the cutting edge PHP version for it. Currently our internal "framework" uses PHP 7.4, but with a PHP 5.6 coding style. Again: I can't wait! I can't do much but thank everyone who spends their time to make PHP evolve. Thank you all! Regards, Erick Em sex., 19 de mai. de 2023 às 17:48, Larry Garfield escreveu: > On Mon, May 8, 2023, at 9:38 PM, Larry Garfield wrote: > > Ilija Tovilo and I would like to offer another RFC for your > > consideration. It's been a while in coming, and we've evolved the > > design quite a bit just in the last week so if you saw an earlier draft > > of it in the past few months, I would encourage you to read it over > > again to make sure we're all on the same page. I'm actually pretty > > happy with where it ended up, even if it's not the original design. > > This approach eliminates several hard-to-implement edge cases while > > still providing a lot of functionality in one package. > > > > https://wiki.php.net/rfc/property-hooks > > Hi folks. Based on feedback we've made a few smaller changes to the RFC. > > Changelog: > > * The sections describing isset/unset and magic methods have been > rewritten to be clearer. Nothing changed in the actual behavior, it is now > just explained better. > > * Contravariance on the "set" type is now enforced. Ilija figured out how > to make it work. :-) That means a non-contravariant type on the set hook > will now throw an error, as expected. > > * After extensive discussion with Nicolas Grekas, we've decided to allow > references in a very narrow case. Specifically, on a *virtual property* > (one that has no inherent backing store), you may implement a `` hook > instead of `get`, and the value it returns will be returned by reference, > and may be captured using $foo =& $bar->baz; We determined that it is a > bit better for BC (in the rare cases that you actually want to get a > reference to a property, you can, even if it requires a little more work), > doesn't break anything else, and is consistent with the way `&__get` > behaves. __get/__set are basically "anonymous virtual properties", so now > they behave the same way. By the same token, setting by reference is still > not allowed, which is also true for __set today. > > As there was no other interest in it stated, we're going to hold off on an > `unset` hook at this time. Given the earlier discussion I think there is a > valid use case for it, so it would be a worthwhile follow up RFC in the > future, but for the moment we want to keep it simple. > > There also doesn't seem to be much interest in specifying which hook gets > the double-shortened syntax. I can see the argument for it, but it would > increase the typing in a common case for an unclear benefit, and only one > person expressed any interest in it. So we're not going to go that route. > > There's two items still pending. > > 1. Ilija is experimenting with the `parent::$prop::get()` syntax, to see > if either the syntax or implementation can be simplified. There may or may > not be a small change here as a result, TBD. > > 2. Ilija still has to verify that foreach() can work with virtual > properties as the RFC currently describes. The implementation details are > thornier than they seem, so that still needs some validation and testing. > > Assuming both of those get sorted out soon, we will probably call a vote > around the end of the month, give or take. > > Cheers. > > --Larry Garfield > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Mon, May 8, 2023, at 9:38 PM, Larry Garfield wrote: > Ilija Tovilo and I would like to offer another RFC for your > consideration. It's been a while in coming, and we've evolved the > design quite a bit just in the last week so if you saw an earlier draft > of it in the past few months, I would encourage you to read it over > again to make sure we're all on the same page. I'm actually pretty > happy with where it ended up, even if it's not the original design. > This approach eliminates several hard-to-implement edge cases while > still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks Hi folks. Based on feedback we've made a few smaller changes to the RFC. Changelog: * The sections describing isset/unset and magic methods have been rewritten to be clearer. Nothing changed in the actual behavior, it is now just explained better. * Contravariance on the "set" type is now enforced. Ilija figured out how to make it work. :-) That means a non-contravariant type on the set hook will now throw an error, as expected. * After extensive discussion with Nicolas Grekas, we've decided to allow references in a very narrow case. Specifically, on a *virtual property* (one that has no inherent backing store), you may implement a `` hook instead of `get`, and the value it returns will be returned by reference, and may be captured using $foo =& $bar->baz; We determined that it is a bit better for BC (in the rare cases that you actually want to get a reference to a property, you can, even if it requires a little more work), doesn't break anything else, and is consistent with the way `&__get` behaves. __get/__set are basically "anonymous virtual properties", so now they behave the same way. By the same token, setting by reference is still not allowed, which is also true for __set today. As there was no other interest in it stated, we're going to hold off on an `unset` hook at this time. Given the earlier discussion I think there is a valid use case for it, so it would be a worthwhile follow up RFC in the future, but for the moment we want to keep it simple. There also doesn't seem to be much interest in specifying which hook gets the double-shortened syntax. I can see the argument for it, but it would increase the typing in a common case for an unclear benefit, and only one person expressed any interest in it. So we're not going to go that route. There's two items still pending. 1. Ilija is experimenting with the `parent::$prop::get()` syntax, to see if either the syntax or implementation can be simplified. There may or may not be a small change here as a result, TBD. 2. Ilija still has to verify that foreach() can work with virtual properties as the RFC currently describes. The implementation details are thornier than they seem, so that still needs some validation and testing. Assuming both of those get sorted out soon, we will probably call a vote around the end of the month, give or take. Cheers. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
> Secondary votes are generally discouraged. I can see the argument for > wanting a short-short version of set, given how common the validation use > case is, but => is almost universally the "evaluates to" symbol, so using > that for a set operation rather than get just feels weirdly inconsistent. If > there were a set-only shorthand, it should be something else. > > That said, the ideal for validation would probably be guard clauses, like > this, but that would be a completely different RFC for another time. > ``` > function foo(string $name where strlen($name) < 10) { ... } > > class Foo { > public function __construct( > public string $name where strlen($name) < 10; > ) {} > } > ``` ```guard``` seems a subset feature of ```hook```, although you want to expand its use case in parameter. Property and parameter are variable. If ```guard``` can be implemented in both case as you write above, theoretically ```hook``` can be either. I will choose ```hook``` rather than ```guard``` to anticipate future expansion. Isn't it better to choose one broad concept than many? I found a contradiction here. Previously you said that: > ... the problem with omitting the {} is that it creates yet another syntax > variant. That makes it harder for the parser, for static analyzers, for > user-space parsing tools like php-parser, etc. That's more work for everyone > for fairly little gain. And here, you introduce a syntax variant. Is it really significant if we introduce a new ```where``` keyword ```compared to the already used ```get``` keyword? I will clarify here in case there is misunderstanding: * If we have more than one hook per property, then the syntax will be the same as proposed by RFC. * If we have only one hook per property, than the syntax are: ``` public function __construct( public string $prop1 get => strtoupper($this->_prop1), ){} public function __construct( public string $prop2 set => $field = strtolower($value), ){} public function __construct( public string $prop3 get { $temp = strtoupper($this->_prop1); return substr($temp, 0, 10) . '...'; }, ){} public function __construct( public string $prop4 set { $temp = strtolower($value); $field = substr($temp, 0, 10); }, ){} ``` Note: Please ignore any error. The ending comma is actually part of the parameter list, not a hook. So it becomes optional if the param is only one or it is the last param. All the examples are constructor property promotion, because that is my only concern. Because the space is limited, the more consistent the code, the better. If I have to write hooks outside CPP, I don't mind using the other syntax. There's plenty of room to fill, and consistency is tolerable. Should we postpone the implementation of the shortest version? Hopefully we have enough time to decide which one will be implemented next. > > ... Ilija also noted to me off-list that you could also have a set hook that > throws an exception rather than just being null, which would also work to > prevent writes. Such a coincidence. I was going to revise my code: ``` // cache once and freeze, // and without additional hidden property // in case asymmetric visibility in not implemented yet public string $prop1 { get => $field ??= $this->heavyTask($this->propx, $prop->y); set => throw new Exception("prop1 is read only"); } ``` > I think an unset hook is a fine addition in the future. The way the code is > implemented it should be straightforward to add. However, it feels like > scope creep to include it right now, especially when there are workarounds > available. If there's a clear consensus from voters to include it, though, > we can consider that. (Meaning, anyone that would favor including an unset > hook now, speak up or we'll assume it's better to stick with just get/set for > now.) +1 for including ```unset``` as part of this RFC. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Mon, May 15, 2023, at 8:12 PM, Hendra Gunawan wrote: >> For the second, the problem with omitting the {} is that it creates yet >> another syntax variant. That makes it harder for the parser, for static >> analyzers, for user-space parsing tools like php-parser, etc. That's more >> work for everyone for fairly little gain. > > Sad to read that. Making one of them as the shortest shorthand feels > like a picky decision. Some people agree with ```get```. Some people > will argue that ```set``` deserves more than ```get```. Personally, I > choose ```set``` to be the shortest shorthand as it is more relevant > with constructor property promotion and value object. Do we need a 2nd > vote for this one? Secondary votes are generally discouraged. I can see the argument for wanting a short-short version of set, given how common the validation use case is, but => is almost universally the "evaluates to" symbol, so using that for a set operation rather than get just feels weirdly inconsistent. If there were a set-only shorthand, it should be something else. That said, the ideal for validation would probably be guard clauses, like this, but that would be a completely different RFC for another time. function foo(string $name where strlen($name) < 10) { ... } class Foo { public function __construct( public string $name where strlen($name) < 10; ) {} } >> What we really would need here is asymmetric visibility. No set hook, but >> make the property private(set) so that trying to write to it gives an error, >> as it should. > > So if asymmetric visibility is implemented, will my code be this simple? > ``` > // cache once and freeze, > // and without additional hidden property > public private(set) string $prop1 { > get => $field ??= $this->heavyTask($this->propx, $prop->y); > } > ``` If you don't want cache clearing, yes. Ilija also noted to me off-list that you could also have a set hook that throws an exception rather than just being null, which would also work to prevent writes. For clearing that cached value, I think an unset hook is probably the best way, with either approach. >> For cache clearing, the best way to do that is probably with an unset hook. >> That's been omitted from the RFC for now for simplicity, but that sounds >> like it would be an argument to introduce it later. > > I was going to write about this one. IMO, why do we need to provide > additional hidden properties, when we are able to store the cache > directly into it? Obviously we need a ```unset``` hook. I think an unset hook is a fine addition in the future. The way the code is implemented it should be straightforward to add. However, it feels like scope creep to include it right now, especially when there are workarounds available. If there's a clear consensus from voters to include it, though, we can consider that. (Meaning, anyone that would favor including an unset hook now, speak up or we'll assume it's better to stick with just get/set for now.) --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
> (Also, when replying, please please remove duplicate names from the to/cc > line. I just got double copies of everything in this thread this morning. > I'm on the list, I don't need to be CCed.) Sorry about that. Not my habit before. > For the second, the problem with omitting the {} is that it creates yet > another syntax variant. That makes it harder for the parser, for static > analyzers, for user-space parsing tools like php-parser, etc. That's more > work for everyone for fairly little gain. Sad to read that. Making one of them as the shortest shorthand feels like a picky decision. Some people agree with ```get```. Some people will argue that ```set``` deserves more than ```get```. Personally, I choose ```set``` to be the shortest shorthand as it is more relevant with constructor property promotion and value object. Do we need a 2nd vote for this one? > Removing the {} entirely from all forms makes it harder to denote where the > list of hooks begins and ends. They would probably have to be > comma-separated, like this: > > public string $foo > get { return $this->bar; }, > set { $this->bar = $value; }; > > Which I'd argue is harder to read anyway, because you have to be careful of > the very small , and ; marks. The {} is just easier for humans to parse as > well as the machine. Looks like it's not more simple compared to the other one. > What we really would need here is asymmetric visibility. No set hook, but > make the property private(set) so that trying to write to it gives an error, > as it should. So if asymmetric visibility is implemented, will my code be this simple? ``` // cache once and freeze, // and without additional hidden property public private(set) string $prop1 { get => $field ??= $this->heavyTask($this->propx, $prop->y); } ``` > For cache clearing, the best way to do that is probably with an unset hook. > That's been omitted from the RFC for now for simplicity, but that sounds like > it would be an argument to introduce it later. I was going to write about this one. IMO, why do we need to provide additional hidden properties, when we are able to store the cache directly into it? Obviously we need a ```unset``` hook. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Mon, May 15, 2023, at 8:32 AM, Lynn wrote: > It's starting to get crowded in object constructors. The following example > is so much more readable and maintainable imo. Would it be possible to > still add the quick assignment as a language feature? I'm personally not > happy having property definitions in both the class body _and_ the > constructor signature. > > ```php > class User { > private string $first; > private string $last; > public string $fullName { > get => $this->first . ' ' . $this->last; > set => [$this->first, $this->last] = explode(' ', $value, 2); > } > > public function __construct($this->fullName) {} > } > > // vs > > class User { > private string $first; > private string $last; > > public function __construct( > public string $fullName { > get => $this->first . ' ' . $this->last; > set => [$this->first, $this->last] = explode(' ', $value, 2); > } > ) {} > } > > // or > > class User { > private string $first; > private string $last; > public string $fullName { > get => $this->first . ' ' . $this->last; > set => [$this->first, $this->last] = explode(' ', $value, 2); > } > > public function __construct(string $fullName) > { > $this->fullName = $fullName; > } > } The last version skips constructor promotion entirely, so will absolutely work. For this case, that's frankly the best approach, since you're right, the constructor gets rather messy otherwise. Changing the syntax and semantics for CPP itself (as in the first code block above) is considerably out of scope for this RFC. I recall someone pointing out why double-declaring the property would cause problems, but I forget the reason. In any case, another promotion syntax would be a topic for another RFC. I don't recall off hand the reasons Nikita had for choosing the syntax that ended up being used. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
Missed one... On Mon, May 15, 2023, at 8:14 AM, Hendra Gunawan wrote: > Can the engine detect these logical errors? > ``` > public string $fullName = "hendra gunawan" => $this->first . " " . > $this->last; > > // or with my proposal: > public string $fullName = "hendra gunawan" get => $this->first . " " . > $this->last; > > // or even this one: > public string $fullName = "hendra gunawan" { > get => $this->first . " " . $this->last; > set => [$this->first, $this->last] = explode(" ", $value); > ``` > > Explanation: > There is no automatic backing store value created to store the default value. > > Terima Kasih. Those would be compile-time syntax errors, yes. (Or possibly link time, if inheritance is involved, but still before execution time.) --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
Consolidating all replies into a single message. Please try to keep them together so it's easier to respond to. (Also, when replying, please please remove duplicate names from the to/cc line. I just got double copies of everything in this thread this morning. I'm on the list, I don't need to be CCed.) On Sun, May 14, 2023, at 11:41 PM, Hendra Gunawan wrote: > Hi Larry. > > ``` > public string $fullName => $this->first . " " . $this->last; > ``` > 1. Suppose that I forgot to declare ```$this->first```. Based on the > "deprecate dynamic properties" proposal, will I get an error/warning? Correct, it will behave the same as if you had a fullName() method that accessed an undefined $first property. > 2. The shorthand notations supported (the shortest one) creates > impaired syntax, and not pretty to look at for constructor property > promotion. > > ``` > public function __construct( > public string $prop1 => strtoupper($this->_prop1), > public string $prop2 {set => $field = strtolower($value);}, > ){} > ``` Well, the first is not really valid anyway. That creates a virtual property with no set hook, which when you pass a value to it in the constructor call will give an error that you are trying to write to a virtual property. So that's already a non-issue. For the second, the problem with omitting the {} is that it creates yet another syntax variant. That makes it harder for the parser, for static analyzers, for user-space parsing tools like php-parser, etc. That's more work for everyone for fairly little gain. Removing the {} entirely from all forms makes it harder to denote where the list of hooks begins and ends. They would probably have to be comma-separated, like this: public string $foo get { return $this->bar; }, set { $this->bar = $value; }; Which I'd argue is harder to read anyway, because you have to be careful of the very small , and ; marks. The {} is just easier for humans to parse as well as the machine. > Suppose that I just want to cache once and freeze, and I don't want to > create additional hidden property. Please make a judgement on the > validity of this syntax: > ``` > public string $prop1 { > get => $field ??= $this->heavyTask($this->propx, $prop->y); > set => null; > } > ``` > > Explanation: > * Since the ```get``` hook uses ```$field```, the engine will create a > backing store value with name ```$prop1```, and will be filled at the > first call only. The later call will use the already stored value. > * Since no new value is assigned to ```$field``` in the ```set``` > hook, the value stored in ```$prop1``` is still the same as before. > * Since any return statement will be discharged in ```set``` hook, the > assignment chaining is safe to use and the value which is transferred > is alway the rightmost value (not the value returned by the ```set``` > hook). > ``` > $varx = $obj->prop1 = "hello"; // $varx value is "hello", and > $obj->prop1 value is unchanged > ``` An interesting approach. It should work as you describe, but there's two reasons I would discourage it: 1. A "set that doesn't set" creates unexpected behavior for callers. If I call set, I expect something to happen. It would be rather confusing to call set and not set things. 2. It doesn't actually allow a cache clearing option. What we really would need here is asymmetric visibility. No set hook, but make the property private(set) so that trying to write to it gives an error, as it should. For cache clearing, the best way to do that is probably with an unset hook. That's been omitted from the RFC for now for simplicity, but that sounds like it would be an argument to introduce it later. Asymmetric visibility would be the higher priority, though. > But, this statement below is NOT ALWAYS correct for "cache once and freeze": > ``` > public string $prop1 { > set => $field ??= $this->heavyTask($this->propx, $prop->y); > } > ``` > Explanation: > * Since default ```get``` hook can be called before ```set``` hook, > backing store value with name ```$prop1``` will still be empty. > * Otherwise, I have to duplicate the body of the ```set``` hook into > ```get``` hook to prevent an emptiness backing store. > > Please give a comment. > Thanks. Correct; while this syntax would compile, it would result in the value assigned to the property being ignored, and then the other heavyTask() value assigned to it, but that still wouldn't ensure it was available the first time you called `get`. That's probably not what anyone wants. It looks like you answered your own question on the interface point, so I'll leave that be. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
> If there is no forward compatibility consideration, can we simplify > interface definition to this one? > ``` > interface IFace > { > public string $readable; > public string $writeable; > public string $both; > } > ``` After carefully reading the proposal again, I think I know the answer for my own question. Short answer: no, we still need ```{ get; }``` to enforce the implemented class. There are two different things here: 1. enforcing the implemented class 2. enforcing the caller site If there are only ordinary properties, then ```{ get; }``` is truly useless at the moment. On the other hand, virtual properties need rules to be enforced, since there is no default hook given to it. Since PHP lacks method definition enforcement at the caller site, I assume that property would suffer the same. Since we don't know what type of property is in the caller site, static analysis tools can benefit from ```{ get; }``` to produce a warning that we should not assign value to the property. A more complex check should be performed to the implemented class because the property type can be determined directly (if i am not wrong). ``` interface IFace { public string $readable1 { get; } public string $readable2 { get; } } class CX implements IFace { private string $_propx; public string $readable1; public string $readable2 { get => $this->_propx; set => $this->_propx = $value; } public function consumeIt(IFace $par) { // these statements should trigger warning by SA tools $par->readable1 = "hello"; $par->readable2 = "world"; // OK $this->readable1 = "hello"; // this statement should trigger error by SA tools $this->readable2 = "hello"; } } ``` -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
> ```php > class User { > private string $first; > private string $last; > public string $fullName { > get => $this->first . ' ' . $this->last; > set => [$this->first, $this->last] = explode(' ', $value, 2); > } > > public function __construct($this->fullName) {} > } > ``` Not entirely true, you created redundancy code for ```$fullName```. This is why we created constructor property promotion: to eliminate redundancy. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Mon, May 15, 2023 at 1:41 AM Hendra Gunawan wrote: > 2. The shorthand notations supported (the shortest one) creates > impaired syntax, and not pretty to look at for constructor property > promotion. > It's starting to get crowded in object constructors. The following example is so much more readable and maintainable imo. Would it be possible to still add the quick assignment as a language feature? I'm personally not happy having property definitions in both the class body _and_ the constructor signature. ```php class User { private string $first; private string $last; public string $fullName { get => $this->first . ' ' . $this->last; set => [$this->first, $this->last] = explode(' ', $value, 2); } public function __construct($this->fullName) {} } // vs class User { private string $first; private string $last; public function __construct( public string $fullName { get => $this->first . ' ' . $this->last; set => [$this->first, $this->last] = explode(' ', $value, 2); } ) {} } // or class User { private string $first; private string $last; public string $fullName { get => $this->first . ' ' . $this->last; set => [$this->first, $this->last] = explode(' ', $value, 2); } public function __construct(string $fullName) { $this->fullName = $fullName; } } ```
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Tue, May 9, 2023 at 4:38 AM Larry Garfield wrote: > > Ilija Tovilo and I would like to offer another RFC for your consideration. > It's been a while in coming, and we've evolved the design quite a bit just in > the last week so if you saw an earlier draft of it in the past few months, I > would encourage you to read it over again to make sure we're all on the same > page. I'm actually pretty happy with where it ended up, even if it's not the > original design. This approach eliminates several hard-to-implement edge > cases while still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks > > -- > Larry Garfield > la...@garfieldtech.com Hi Larry Can the engine detect these logical errors? ``` public string $fullName = "hendra gunawan" => $this->first . " " . $this->last; // or with my proposal: public string $fullName = "hendra gunawan" get => $this->first . " " . $this->last; // or even this one: public string $fullName = "hendra gunawan" { get => $this->first . " " . $this->last; set => [$this->first, $this->last] = explode(" ", $value); ``` Explanation: There is no automatic backing store value created to store the default value. Terima Kasih. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Tue, May 9, 2023 at 4:38 AM Larry Garfield wrote: > > Ilija Tovilo and I would like to offer another RFC for your consideration. > It's been a while in coming, and we've evolved the design quite a bit just in > the last week so if you saw an earlier draft of it in the past few months, I > would encourage you to read it over again to make sure we're all on the same > page. I'm actually pretty happy with where it ended up, even if it's not the > original design. This approach eliminates several hard-to-implement edge > cases while still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks > > -- > Larry Garfield > la...@garfieldtech.com Hi, Larry ``` interface IFace { public string $readable { get; } public string $writeable { set; } public string $both { get; set; } } ``` How important is ```{ get; }``` statement (and friends) in the interface? Since PHP does not enforce method definition existence in caller site, this code is valid (at least at compile time): ``` interface IA { // ... } interface IB { public function doIt(IA $par1); } class CA1 implements IA { // makeIt is not part of IA public function makeIt() { echo " makeIt() is called"; } } class CA2 implements IA {} class CB implements IB { public function doit(IA $par1) { // makeIt is not enforced to be invalid $par1->makeit(); } } $a1 = new CA1; $a2 = new CA2; $b = new CB; $b->doIt($a1); // valid $b->doIt($a2); // invalid at runtime ``` IMO, ```{ get; }``` (and friends) only useful if there are: * definition existence enforcement or implemented asymmetric visibility * AND no default hook implementation provided. I assume that ```{ get; }``` do exist in the property accessors proposal because there is no default hook implementation. Whether there is already implemented property definition existence enforcement or not, i don't know. If yes, then all things are in the right place. If not, it feels like a half baked feature, just like the method was: the error will pop up at runtime. The only positive value is ```{ get; }``` can still be consumed by static analysis tools. ``` class CX { public function consumeIt(IFace $par) { // this statement should trigger error // produced by engine or SA tools $par->readable = "hello"; } } ``` Things will be different with property hooks. Without definition existence enforcement nor implemented asymmetric visibility, static analysis tools will give misconception about unlisted hooks if there is error/warning message. ``` class CX { public function consumeIt(IFace $par) { // default hook is provided by engine // any message is not relevant for this valid statement $par->readable = "hello"; } } ``` If there is no forward compatibility consideration, can we simplify interface definition to this one? ``` interface IFace { public string $readable; public string $writeable; public string $both; } ``` Thanks in advance. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Tue, May 9, 2023 at 4:38 AM Larry Garfield wrote: > > Ilija Tovilo and I would like to offer another RFC for your consideration. > It's been a while in coming, and we've evolved the design quite a bit just in > the last week so if you saw an earlier draft of it in the past few months, I > would encourage you to read it over again to make sure we're all on the same > page. I'm actually pretty happy with where it ended up, even if it's not the > original design. This approach eliminates several hard-to-implement edge > cases while still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks > > -- > Larry Garfield > la...@garfieldtech.com > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > Hi Larry. Suppose that I just want to cache once and freeze, and I don't want to create additional hidden property. Please make a judgement on the validity of this syntax: ``` public string $prop1 { get => $field ??= $this->heavyTask($this->propx, $prop->y); set => null; } ``` Explanation: * Since the ```get``` hook uses ```$field```, the engine will create a backing store value with name ```$prop1```, and will be filled at the first call only. The later call will use the already stored value. * Since no new value is assigned to ```$field``` in the ```set``` hook, the value stored in ```$prop1``` is still the same as before. * Since any return statement will be discharged in ```set``` hook, the assignment chaining is safe to use and the value which is transferred is alway the rightmost value (not the value returned by the ```set``` hook). ``` $varx = $obj->prop1 = "hello"; // $varx value is "hello", and $obj->prop1 value is unchanged ``` But, this statement below is NOT ALWAYS correct for "cache once and freeze": ``` public string $prop1 { set => $field ??= $this->heavyTask($this->propx, $prop->y); } ``` Explanation: * Since default ```get``` hook can be called before ```set``` hook, backing store value with name ```$prop1``` will still be empty. * Otherwise, I have to duplicate the body of the ```set``` hook into ```get``` hook to prevent an emptiness backing store. Please give a comment. Thanks. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Tue, May 9, 2023 at 4:38 AM Larry Garfield wrote: > > Ilija Tovilo and I would like to offer another RFC for your consideration. > It's been a while in coming, and we've evolved the design quite a bit just in > the last week so if you saw an earlier draft of it in the past few months, I > would encourage you to read it over again to make sure we're all on the same > page. I'm actually pretty happy with where it ended up, even if it's not the > original design. This approach eliminates several hard-to-implement edge > cases while still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks > > -- > Larry Garfield > la...@garfieldtech.com > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > Hi Larry. ``` public string $fullName => $this->first . " " . $this->last; ``` 1. Suppose that I forgot to declare ```$this->first```. Based on the "deprecate dynamic properties" proposal, will I get an error/warning? 2. The shorthand notations supported (the shortest one) creates impaired syntax, and not pretty to look at for constructor property promotion. ``` public function __construct( public string $prop1 => strtoupper($this->_prop1), public string $prop2 {set => $field = strtolower($value);}, ){} ``` My suggestion is: use get/set keyword immediately after property name/default value rather than "=>" or "{" without losing multiline statements. ``` public function __construct( public string $prop1 get => strtoupper($this->_prop1), public string $prop2 set => $field = strtolower($value), public string $prop3 get { $temp = strtoupper($this->_prop1); return substr($temp, 0, 10) . '...'; } public string $prop4 set { $temp = strtolower($value); $field = substr($temp, 0, 10); } ){} ``` This syntax is aligned with a single statement if/for/foreach. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
> > Regarding $field vs. $this->propName, there's a few reasons we went that > route. Overall I think this is a really good proposal, but you might want to consider a second vote for that particular syntax. `$field` vs `$this->propName` feels a little magical. It's a simpler magic than actual magic methods — it's magic that static analysis tools can quickly reason about (as they can with promoted properties). But I can imagine developers coming across this particular syntax in a PR and thinking "that looks like a bug". I know it's a few extra keypresses, but I think $this->propName is easier to scan, and more familiar (given this RFC introduces a lot of other new syntax).
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Wed, May 10, 2023, at 11:35 AM, Robert Landers wrote: >> Regarding $field vs. $this->propName, there's a few reasons we went that >> route. >> >> 1. It's shorter and less typing for what will be a common pattern. >> 2. That makes it consistent between hook implementations. In working on >> examples, I found many cases where I was adding basically the same line to >> multiple hooks on the same class. Making the code easier to copy-paste >> seems like a win. >> 3. It also will be helpful if hook packages are added in the future, as >> they'll need a more "generic" way to access the backing property. (See >> Future Scope.) Eg, "$field = someLogic($value)" applied to a dozen >> different properties; it wouldn't work if it was "$this->specificProperty = >> someLogic($value)". >> 4. We're used to our eyes glossing over "$this->propName", as it's so >> common. Having a separate name to mentally scan for to determine if a >> property is virtual or not seems like it will be helpful in practice. >> 5. There's precedent for it: Kotlin has almost the same functionality as we >> describe here, and uses a `field` variable in the exact same way. >> >> So it's mainly an ergonomics argument rather than a technical one. "Compile >> time macro" means it translates to the same AST as if you'd used >> $this->propName. There's precedent for that. Constructor Property >> Promotion works basically the same way. > > With using a common name for say, $value, open the door for a library > of common hook implementations (eventually)? > > Maybe something like: > > class User { > // snip > public string $fullName { get => FancyLibrary\fullName(...) } > // snip > } > > I could imagine something like this would be a huge boon to PHP if it > automatically bound the closure. $field is only available inside the hook itself, not inside functions called from it. But that does mean you could do this instead: class User { // snip public string $fullName { get => FancyLibrary\fullName($field) } // snip } Which, yes, should work fine. If such a library actually became popular, that would be an argument to implement the "property hook packages" or "property traits" concept that Swift has, as noted in Future Scope. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
> Regarding $field vs. $this->propName, there's a few reasons we went that > route. > > 1. It's shorter and less typing for what will be a common pattern. > 2. That makes it consistent between hook implementations. In working on > examples, I found many cases where I was adding basically the same line to > multiple hooks on the same class. Making the code easier to copy-paste seems > like a win. > 3. It also will be helpful if hook packages are added in the future, as > they'll need a more "generic" way to access the backing property. (See > Future Scope.) Eg, "$field = someLogic($value)" applied to a dozen different > properties; it wouldn't work if it was "$this->specificProperty = > someLogic($value)". > 4. We're used to our eyes glossing over "$this->propName", as it's so common. > Having a separate name to mentally scan for to determine if a property is > virtual or not seems like it will be helpful in practice. > 5. There's precedent for it: Kotlin has almost the same functionality as we > describe here, and uses a `field` variable in the exact same way. > > So it's mainly an ergonomics argument rather than a technical one. "Compile > time macro" means it translates to the same AST as if you'd used > $this->propName. There's precedent for that. Constructor Property Promotion > works basically the same way. With using a common name for say, $value, open the door for a library of common hook implementations (eventually)? Maybe something like: class User { // snip public string $fullName { get => FancyLibrary\fullName(...) } // snip } I could imagine something like this would be a huge boon to PHP if it automatically bound the closure. -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Tue, May 9, 2023, at 5:46 PM, Larry Garfield wrote: >> I have a bigger concern: the take on references contradicts with the intro >> about BC breaks: turning a materialized property into virtual one would >> break BC as far as refs are concerned. One idea to fix that: add a ref >> hook, that must return a reference. If not implemented => Error when trying >> to get-by-ref. This could also help solve the $foo->array[] case (including >> the asym-visiblity issue). > > That might be possible. The issue there is that the returned ref would > still be bypassing the get/set hooks, so you're just adding a way to > dance around the existing hook implementations, which is exactly what > we're trying to avoid. Also, what would that hook even mean if used on > a virtual property? > > Moreover, in practice, getting a reference to a property is extremely > rare, with the exception of array writes. I cannot recall the last > time I even saw some code get a reference to a property. That's why we > felt comfortable just leaving it at is. In an earlier version of the > RFC we had a way for properties to just disable references without > adding any hooks, but removed it on the grounds that it was not worth > the effort. Addendum here: The RFC wasn't clear, in part because I wasn't clear, but the prohibition on [] on properties applies only on set. On get, whatever array value is returned from the hook is just a boring array, which can then be dereferenced to look up a key. I've updated the RFC accordingly to make it clearer what is and isn't allowed with arrays. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Mon, May 8, 2023, at 9:38 PM, Larry Garfield wrote: > Ilija Tovilo and I would like to offer another RFC for your > consideration. It's been a while in coming, and we've evolved the > design quite a bit just in the last week so if you saw an earlier draft > of it in the past few months, I would encourage you to read it over > again to make sure we're all on the same page. I'm actually pretty > happy with where it ended up, even if it's not the original design. > This approach eliminates several hard-to-implement edge cases while > still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks Thanks everyone for your feedback so far. I'm going to collapse the replies into one message to reduce noise. On Tue, May 9, 2023, at 7:57 AM, Tim Düsterhus wrote: > (1) How does the set() hook interact with #[\SensitiveParameter]? Internally, the hook is a method, so it should respect it the same way as any other method. Viz, you should be able to write: ``` public string $foo { set ($[\SensitiveParameter] string $value) { $field = strtolower($foo); } } ``` I'll ask Ilija to add a test to confirm that. > (2) How will a Stack Trace emitted from a hook look like? Please include > an example of the Exception::__toString() output or so. I'll ask Ilija to add a test to his branch and link it here. > (3) ReflectionProperty::getHook(): Will this throw if an invalid hook > name is given or will this return null? Null if you ask for get/set and one doesn't exist. Error if you ask for something other than "get" or "set". We're still keeping it as a single method, though, to make supporting other hooks easier in the future if desired. I've updated the RFC to clarify that. > (4) The "Unaffected PHP Functionality" section is empty. It should > either be filled in or removed. Removed. I don't quite understand the purpose of that section. :-) On Tue, May 9, 2023, at 9:54 AM, Nicolas Grekas wrote: >- does set($value) { mean set(mixed $value) { or set(TypeFromProp >$value) { ? I understand it would be the latter but it might be nice to >clarify (unless I missed it) Conceptually, I believe it means set(TypeFromProp $value). Since at present that cannot be enforced, though, they're basically the same thing. (If someone with more engine-fu than either of us wants to help enforce contravariant types in set, please speak up because we'd prefer to do so.) >- function setFullName => ucfirst is not found in the "set" version Yes it is. Look at the end of the `set` line. >- could parent::$x::set($x) be replaced by parent::$x = $x ? Same for >the get variant? Why not if not? There's a subtle but important distinction here. parent::$x would suggest accessing the parent *property*, ie, its backing value, directly. What is actually intended here is accessing the parent *hook*, ie, its equivalent to parent::setFoo($foo). The property itself is already available as $field. We're open to alternate syntaxes for accessing the parent accessor syntax if people have good (and easily implementable) suggestions. >- readonly: could this be supported by materializing them, using the >storage for memoization after first access? that'd be quite powerful That was one of my early ideas, as it then became a cheap form of cached lazy property. However, that then means there's no meaningful way to unset the cache. In the end we decided that there were too many nooks and crannies to readonly to try and make sense of. (The more I use it, the more I think readonly was a mistake and we should have gone straight to aviz.) (As a side note, if we had aviz, then we could use the field itself as a cache by making writes private, like so: public string $name => $field ??= $this->first . $this->last; But right now that would also imply public-set, which we wouldn't want. Aviz would solve that issue entirely. Another reason aviz is an important and useful feature. :-) ) What a readonly flag on a set-only property means... I have no idea. >- I'm not sure we need ReflectionProperty::getHook('set') when we can >do getHooks()['set'] ?? null The double-methods were mainly for consistency with the rest of the Reflection API, which tends to have both getFoo(): object and getFoos(): array options. It's no more redundant than the rest of Reflection. >- What does ReflectionMethod::getName return on a hook? And getClosure? Either "get" or some hashed string that includes "get". I'm not sure off hand. I'll have to check with Ilija. >- Should we add ReflectionProperty::IS_VIRTUAL ? Funny story. I just asked Ilija this, and he said he already did add it for testing purpose but forgot to tell me. :-) RFC updated. >- I'm a bit surprised by the possibility of adding attributes to hooks. >I'm not sure I see the use case and I think this might be confusing in >addition to attributes on the
RE: [PHP-DEV] [RFC] Property hooks, nee accessors
> Ilija Tovilo and I would like to offer another RFC for your consideration. > It's > been a while in coming, and we've evolved the design quite a bit just in the > last > week so if you saw an earlier draft of it in the past few months, I would > encourage you to read it over again to make sure we're all on the same page. > I'm actually pretty happy with where it ended up, even if it's not the > original > design. This approach eliminates several hard-to-implement edge cases while > still providing a lot of functionality in one package. > > https://wiki.php.net/rfc/property-hooks +1 from me, I've used it in C# and it makes for clean code and less boilerplate. -Jeff -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
It looks great! Thank you so, so much. I've been wanting this for a long time. I have used properties in C# and it's very useful. I'm reading this RFC since it was in draft. =) One thing that I did not understand was this piece of code: class C { public array $_names; public string $names { set { $this->*_prop* = explode(',', $value); // *< Where this "_prop" is coming from?* } } } $c = new C(); var_dump($c->names = 'Ilija,Larry'); // 'Ilija,Larry' var_dump($c->_names); // ['Ilija', 'Larry'] Does "_prop" have any special meaning or is it just a typo? Thanks one more time for this! Regards, Erick Em ter., 9 de mai. de 2023 às 08:52, Dik Takken escreveu: > > > On 08-05-2023 23:38, Larry Garfield wrote: > > Ilija Tovilo and I would like to offer another RFC for your > consideration. It's been a while in coming, and we've evolved the design > quite a bit just in the last week so if you saw an earlier draft of it in > the past few months, I would encourage you to read it over again to make > sure we're all on the same page. I'm actually pretty happy with where it > ended up, even if it's not the original design. This approach eliminates > several hard-to-implement edge cases while still providing a lot of > functionality in one package. > > > > https://wiki.php.net/rfc/property-hooks > > > > Thanks for all the work that has gone into this. It looks great. The > ability to add properties to interfaces is also really nice. > > One thing that concerns me is the following: "the use of [] on any > property (with or without a key) will result in a runtime error being > thrown". While the intent of the RFC is to allow adding hooks without > causing BC breaks, this detail does introduce a BC break. And the break > may get introduced without realizing it. > > I'm not sure which solution would be best here: Just accept the > limitations for arrays (same as for list properties in Python) or forbid > the use of hooks for array properties? I'm leaning towards accepting the > limitations, like Python does. Then it is up to the API designer to > decide if a property hook is the right tool for the job or not. > > Regards, > Dik > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On Mon, May 8, 2023 at 11:38 PM Larry Garfield wrote: > Ilija Tovilo and I would like to offer another RFC for your > consideration. It's been a while in coming, and we've evolved the design > quite a bit just in the last week so if you saw an earlier draft of it in > the past few months, I would encourage you to read it over again to make > sure we're all on the same page. I'm actually pretty happy with where it > ended up, even if it's not the original design. This approach eliminates > several hard-to-implement edge cases while still providing a lot of > functionality in one package. > > https://wiki.php.net/rfc/property-hooks Thank you! Looks interesting, I will need to think about things before more qualitative feedback. An error maybe, the "class C" example in "Detailed Proposal > set" uses a "$this->_prop", but probably meant to use $this->_names, since private array $_names; is declared in the example. I think $field should be its own "chapter". Its a central part of the proposal that should be clarified early and so that readers don't accidentally skip it. I am also confused why $field exists when $this->propertyName works and why its not recommended to be used. Is $field a reference? or does the "compile time macro" part mean its replaced at compile time? Ifso, this feels different to anything else PHP, i am leaning towards $this->propertyName if there are no other compelling reasons why $field should be used. > > > -- > Larry Garfield > la...@garfieldtech.com > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
On 08-05-2023 23:38, Larry Garfield wrote: Ilija Tovilo and I would like to offer another RFC for your consideration. It's been a while in coming, and we've evolved the design quite a bit just in the last week so if you saw an earlier draft of it in the past few months, I would encourage you to read it over again to make sure we're all on the same page. I'm actually pretty happy with where it ended up, even if it's not the original design. This approach eliminates several hard-to-implement edge cases while still providing a lot of functionality in one package. https://wiki.php.net/rfc/property-hooks Thanks for all the work that has gone into this. It looks great. The ability to add properties to interfaces is also really nice. One thing that concerns me is the following: "the use of [] on any property (with or without a key) will result in a runtime error being thrown". While the intent of the RFC is to allow adding hooks without causing BC breaks, this detail does introduce a BC break. And the break may get introduced without realizing it. I'm not sure which solution would be best here: Just accept the limitations for arrays (same as for list properties in Python) or forbid the use of hooks for array properties? I'm leaning towards accepting the limitations, like Python does. Then it is up to the API designer to decide if a property hook is the right tool for the job or not. Regards, Dik -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
Ilija Tovilo and I would like to offer another RFC for your consideration. > It's been a while in coming, and we've evolved the design quite a bit just > in the last week so if you saw an earlier draft of it in the past few > months, I would encourage you to read it over again to make sure we're all > on the same page. I'm actually pretty happy with where it ended up, even > if it's not the original design. This approach eliminates several > hard-to-implement edge cases while still providing a lot of functionality > in one package. > > https://wiki.php.net/rfc/property-hooks > Congrats for the RFC for property hooks, I like it all, including abbreviated forms, $value as default name, etc. Some notes: - does set($value) { mean set(mixed $value) { or set(TypeFromProp $value) { ? I understand it would be the latter but it might be nice to clarify (unless I missed it) - function setFullName => ucfirst is not found in the "set" version - could parent::$x::set($x) be replaced by parent::$x = $x ? Same for the get variant? Why not if not? - readonly: could this be supported by materializing them, using the storage for memoization after first access? that'd be quite powerful - I'm not sure we need ReflectionProperty::getHook('set') when we can do getHooks()['set'] ?? null - What does ReflectionMethod::getName return on a hook? And getClosure? - Should we add ReflectionProperty::IS_VIRTUAL ? - I'm a bit surprised by the possibility of adding attributes to hooks. I'm not sure I see the use case and I think this might be confusing in addition to attributes on the property itself. - For serialization: exclude them from var_export() and serialize(), which don't need virtual props to rebuild the state (you mean json_encode(), not JsonSerializable on that list), call get for var_dump/print_r when it's defined (but ignore exceptions). But (array) / get_mangled_object_vars() / get_object_vars() shouldn't call any "get". I have a bigger concern: the take on references contradicts with the intro about BC breaks: turning a materialized property into virtual one would break BC as far as refs are concerned. One idea to fix that: add a ref hook, that must return a reference. If not implemented => Error when trying to get-by-ref. This could also help solve the $foo->array[] case (including the asym-visiblity issue). Nicolas
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
Hi On 5/8/23 23:38, Larry Garfield wrote: Ilija Tovilo and I would like to offer another RFC for your consideration. It's been a while in coming, and we've evolved the design quite a bit just in the last week so if you saw an earlier draft of it in the past few months, I would encourage you to read it over again to make sure we're all on the same page. I'm actually pretty happy with where it ended up, even if it's not the original design. This approach eliminates several hard-to-implement edge cases while still providing a lot of functionality in one package. https://wiki.php.net/rfc/property-hooks I've read a previous draft and now did another pass through the updated version: (1) How does the set() hook interact with #[\SensitiveParameter]? (2) How will a Stack Trace emitted from a hook look like? Please include an example of the Exception::__toString() output or so. (3) ReflectionProperty::getHook(): Will this throw if an invalid hook name is given or will this return null? (4) The "Unaffected PHP Functionality" section is empty. It should either be filled in or removed. (5) I strongly dislike the doubly abbreviated form of `public string $fullName => $this->first . " " . $this->last;`. Having just the extra '>' in there to distinguish it from a regular property feels non-obvious. Best regards Tim Düsterhus -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: https://www.php.net/unsub.php
Re: [PHP-DEV] [RFC] Property hooks, nee accessors
Hi Larry, pon., 8 maj 2023 o 23:38 Larry Garfield napisał(a): > Ilija Tovilo and I would like to offer another RFC for your > consideration. It's been a while in coming, and we've evolved the design > quite a bit just in the last week so if you saw an earlier draft of it in > the past few months, I would encourage you to read it over again to make > sure we're all on the same page. I'm actually pretty happy with where it > ended up, even if it's not the original design. This approach eliminates > several hard-to-implement edge cases while still providing a lot of > functionality in one package. > > https://wiki.php.net/rfc/property-hooks > Using $this->propertyName directly is supported, but not recommended. Why is that? IMHO in the scope of accessor this is much clearer to me than using the $field. > The following example does make use of $field, however, and thus a backing value will be created, and write operations will simply write to the property as normal. This looks like new magic to me, whether we allow setting and baking the value explicitly or not. I consider this behavior confusing. Overall I vote yes. Cheers, Michał Marcin Brzuchalski