[RFC] Deprecate dynamic properties

  115800
August 25, 2021 10:02 nikita.ppv@gmail.com (Nikita Popov)
Hi internals,

I'd like to propose the deprecation of "dynamic properties", that is
properties that have not been declared in the class (stdClass and
__get/__set excluded, of course):

https://wiki.php.net/rfc/deprecate_dynamic_properties

This has been discussed in various forms in the past, e.g. in
https://wiki.php.net/rfc/locked-classes as a class modifier and
https://wiki.php.net/rfc/namespace_scoped_declares /
https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md
as a declare directive.

This RFC takes the more direct route of deprecating this functionality
entirely. I expect that this will have relatively little impact on modern
code (e.g. in Symfony I could fix the vast majority of deprecation warnings
with a three-line diff), but may have a big impact on legacy code that
doesn't declare properties at all.

Regards,
Nikita
  115801
August 25, 2021 10:14 kjarli@gmail.com (Lynn)
On Wed, Aug 25, 2021 at 12:03 PM Nikita Popov ppv@gmail.com> wrote:

> This RFC takes the more direct route of deprecating this functionality > entirely. I expect that this will have relatively little impact on modern > code (e.g. in Symfony I could fix the vast majority of deprecation warnings > with a three-line diff), but may have a big impact on legacy code that > doesn't declare properties at all. >
The project I maintain is massive and it's full of code that implicitly defines properties. As long as the deprecations are clear, I'm 100% behind this proposal as it will finally give me leverage to fix the code base at some point in time.
  115802
August 25, 2021 10:45 rowan.collins@gmail.com (Rowan Tommins)
On 25/08/2021 11:02, Nikita Popov wrote:
> I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties
This is a bold move, and in principle seems sensible, although I'm slightly scared how many places will need fixing in legacy code bases. I have a couple of concerns with using stdClass as the opt-in mechanism: * The name of that class already leads to a lot of confusion about its purpose - it's not actually "standard" in any way, and new users seeing it as a base class are even more likely to mistake it as some kind of "universal ancestor". Would it be feasible to introduce an alias like "DynamicObject" which more clearly defines its role? * Adding a parent to an existing class isn't always possible, if it already inherits from something else. Perhaps the behaviour could also be available as a trait, which defined stub __get and __set methods, allowing for the replacement of the internal implementation as you've described? Regards, -- Rowan Tommins [IMSoP]
  115804
August 25, 2021 10:52 flaviohbatista@gmail.com (=?UTF-8?Q?Fl=C3=A1vio_Heleno?=)
On Wed, Aug 25, 2021 at 7:46 AM Rowan Tommins collins@gmail.com>
wrote:

> On 25/08/2021 11:02, Nikita Popov wrote: > > I'd like to propose the deprecation of "dynamic properties", that is > > properties that have not been declared in the class (stdClass and > > __get/__set excluded, of course): > > > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > > This is a bold move, and in principle seems sensible, although I'm > slightly scared how many places will need fixing in legacy code bases. > > I have a couple of concerns with using stdClass as the opt-in mechanism: > > * The name of that class already leads to a lot of confusion about its > purpose - it's not actually "standard" in any way, and new users seeing > it as a base class are even more likely to mistake it as some kind of > "universal ancestor". Would it be feasible to introduce an alias like > "DynamicObject" which more clearly defines its role? > > * Adding a parent to an existing class isn't always possible, if it > already inherits from something else. Perhaps the behaviour could also > be available as a trait, which defined stub __get and __set methods, > allowing for the replacement of the internal implementation as you've > described? > > > Regards, > > -- > Rowan Tommins > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > > Although not having voting karma, I'm +1 on this.
I've always preferred explicit over implicit code as it makes the learning path to newcomers a lot easier to grasp. When we talk about legacy code, more frequently than not is that legacy code is unlikely to run on the latest version of PHP, thus I'm not entirely sure if that's a super strong argument against it, but I may be missing something. -- Atenciosamente, Flávio Heleno
  115806
August 25, 2021 11:05 office.hamzaahmad@gmail.com (Hamza Ahmad)
HI Nikita,

What if you consider this instead? Rather allowing STD class as an
exception to dynamic properties, why not introduce STDAbstract?
```php
interface STDClassInterface
{
public function __get(string $name) : mixed;
public function __set(string $name, mixed $value = null) : mixed;
/* * other magic methods */
};
abstract class STDClassAbstract implements STDClassInterface {/* *
interface methods */}
Class STDClass extends SDTClassAbstract{}
``

Best
Hamza

On 8/25/21, Rowan Tommins collins@gmail.com> wrote:
> On 25/08/2021 11:02, Nikita Popov wrote: >> I'd like to propose the deprecation of "dynamic properties", that is >> properties that have not been declared in the class (stdClass and >> __get/__set excluded, of course): >> >> https://wiki.php.net/rfc/deprecate_dynamic_properties > > > This is a bold move, and in principle seems sensible, although I'm > slightly scared how many places will need fixing in legacy code bases. > > I have a couple of concerns with using stdClass as the opt-in mechanism: > > * The name of that class already leads to a lot of confusion about its > purpose - it's not actually "standard" in any way, and new users seeing > it as a base class are even more likely to mistake it as some kind of > "universal ancestor". Would it be feasible to introduce an alias like > "DynamicObject" which more clearly defines its role? > > * Adding a parent to an existing class isn't always possible, if it > already inherits from something else. Perhaps the behaviour could also > be available as a trait, which defined stub __get and __set methods, > allowing for the replacement of the internal implementation as you've > described? > > > Regards, > > -- > Rowan Tommins > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > >
  115809
August 25, 2021 12:35 a.leathley@gmx.net (Andreas Leathley)
On 25.08.21 12:45, Rowan Tommins wrote:
> * Adding a parent to an existing class isn't always possible, if it > already inherits from something else. Perhaps the behaviour could also > be available as a trait, which defined stub __get and __set methods, > allowing for the replacement of the internal implementation as you've > described? > Couldn't this be easily done in userland with the ArrayLikeObject (an
example in the RFC) or something similar, just done as a trait? Maybe having an example trait implementation that basically "imitates" stdClass in terms of dynamic properties would be helpful to show in the RFC, to highlight a possible resolution path for legacy code with this problem. This could be an example implementation: trait DynamicPropertiesTrait {     private array $dynamicProperties = [];     public function &__get(string $name): mixed { return $this->dynamicProperties[$name]; }     public function __isset(string $name): bool { return isset($this->dynamicProperties[$name]); }     public function __set(string $name, mixed $value): void { $this->dynamicProperties[$name] = $value; }     public function __unset(string $name): void { unset($this->dynamicProperties[$name]); } }
  115810
August 25, 2021 12:45 nikita.ppv@gmail.com (Nikita Popov)
On Wed, Aug 25, 2021 at 12:45 PM Rowan Tommins collins@gmail.com>
wrote:

> On 25/08/2021 11:02, Nikita Popov wrote: > > I'd like to propose the deprecation of "dynamic properties", that is > > properties that have not been declared in the class (stdClass and > > __get/__set excluded, of course): > > > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > > This is a bold move, and in principle seems sensible, although I'm > slightly scared how many places will need fixing in legacy code bases. > > I have a couple of concerns with using stdClass as the opt-in mechanism: > > * The name of that class already leads to a lot of confusion about its > purpose - it's not actually "standard" in any way, and new users seeing > it as a base class are even more likely to mistake it as some kind of > "universal ancestor". Would it be feasible to introduce an alias like > "DynamicObject" which more clearly defines its role? > > * Adding a parent to an existing class isn't always possible, if it > already inherits from something else. Perhaps the behaviour could also > be available as a trait, which defined stub __get and __set methods, > allowing for the replacement of the internal implementation as you've > described? >
So, a few thoughts: First of all, I should say that "extends stdClass" is not so much an explicit escape hatch I built into this, it's more something that arises naturally: We obviously need to keep support for dynamic properties on stdClass, and if we do so, I would expect that to apply to subclasses as well. As such, I believe that the "extends stdClass" escape hatch is something that's going to work anyway -- the only question would be whether we want to provide additional opt-ins in the form of interfaces/traits/attributes/etc. Second, I consider "extends stdClass" to be something of a last-ditch option. If you encounter a dynamic property deprecation warning, you should generally resolve it in some other way, and only fall back to "extends stdClass" as the final option. All that said, yes, we could add a trait. It would basically be ArrayLikeObject from the RFC with "class" replaced by "trait". However, I'm not sure this is really worthwhile. The nice thing about extending stdClass is that it a) gives you much more efficient property access than __get/__set and b) matches current behavior. Implementing such a trait, even if bundled, doesn't really give you any advantages over implemening __get/__set yourself. It would not make use of an optimized implementation (or at least, the implementation would still be calling real __get/__set methods) and the behavior would be limited to what the trait provides. A custom implementation is not significantly harder (the minimal implementation is five lines of code) but gives you more control, e.g. you might want just the minimal implementation, or you might want to also support Traversable, have a custom __debugInfo(), etc. My preliminary position would be that if a) you can't avoid dynamic properties in any other way and b) you can't extend stdClass either, then you should go with c) implementing __get/__set yourself, as appropriate for the given use-case. Regards, Nikita
  115811
August 25, 2021 13:51 rowan.collins@gmail.com (Rowan Tommins)
On 25/08/2021 13:45, Nikita Popov wrote:

> We obviously need to keep support for dynamic properties on stdClass, > and if we do so, I would expect that to apply to subclasses as well.
Does that actually follow, though? Right now, there is no advantage to extending stdClass, so no reason to expect existing code to do so, and no reason for people doing so to expect it to affect behaviour.
> Second, I consider "extends stdClass" to be something of a last-ditch > option. If you encounter a dynamic property deprecation warning, you > should generally resolve it in some other way, and only fall back to > "extends stdClass" as the final option.
That's a reasonable argument in terms of the multiple inheritance case. My concern about the name remains though: people already do get confused by the name "stdClass", because it's not in any way "standard", and tells you nothing about what it does. Reading "class Foo extends stdClass" gives the reader no clues what magic behaviour is being inherited; "class Foo extends DynamicObject" would be much more clear. Similarly, "$foo = new DynamicObject; $foo->bar = 42;" is clearer than "$foo = new stdClass; $foo->bar = 42;" Regards, -- Rowan Tommins [IMSoP]
  115812
August 25, 2021 14:00 nikita.ppv@gmail.com (Nikita Popov)
On Wed, Aug 25, 2021 at 3:51 PM Rowan Tommins collins@gmail.com>
wrote:

> On 25/08/2021 13:45, Nikita Popov wrote: > > > We obviously need to keep support for dynamic properties on stdClass, > > and if we do so, I would expect that to apply to subclasses as well. > > Does that actually follow, though? Right now, there is no advantage to > extending stdClass, so no reason to expect existing code to do so, and > no reason for people doing so to expect it to affect behaviour. >
Isn't this a direct consequence of LSP? We can't just drop behavior when extending. Only way for this not to follow would be if we disallowed extending from stdClass entirely, which we presumably don't want to do.
> Second, I consider "extends stdClass" to be something of a last-ditch > > option. If you encounter a dynamic property deprecation warning, you > > should generally resolve it in some other way, and only fall back to > > "extends stdClass" as the final option. > > > That's a reasonable argument in terms of the multiple inheritance case. > > My concern about the name remains though: people already do get confused > by the name "stdClass", because it's not in any way "standard", and > tells you nothing about what it does. > > Reading "class Foo extends stdClass" gives the reader no clues what > magic behaviour is being inherited; "class Foo extends DynamicObject" > would be much more clear. Similarly, "$foo = new DynamicObject; > $foo->bar = 42;" is clearer than "$foo = new stdClass; $foo->bar = 42;" >
Yes, I can see the argument for aliasing stdClass to something more meaningful, even independently of this RFC. I'm not sure it will have a big impact for this use-case though, because using the new name would require polyfilling it, so I'd expect people would stick to the old name in the foreseeable future... Regards, Nikita
  115818
August 25, 2021 14:49 rowan.collins@gmail.com (Rowan Tommins)
On 25/08/2021 15:00, Nikita Popov wrote:
> I'm not sure it will have a big impact for this use-case though, > because using the new name would require polyfilling it, so I'd expect > people would stick to the old name in the foreseeable future...
Not necessarily - it depends what versions you need to support, and what your migration strategy is. Since it's just a deprecation notice initially, you could support 8.1 and 8.2 on the same code base with no changes at all - that's what deprecation notices are for, to give a lead time before changes are mandatory. Once the code base no longer needed to support 8.1, "extends DynamicObject" could be added. For many code bases, that will be long before the feature is actually removed - for a private project, maybe as soon as it's on 8.2 in production. Regards, -- Rowan Tommins [IMSoP]
  115813
August 25, 2021 14:04 chasepeeler@gmail.com (Chase Peeler)
On Wed, Aug 25, 2021 at 9:51 AM Rowan Tommins collins@gmail.com>
wrote:

> On 25/08/2021 13:45, Nikita Popov wrote: > > > We obviously need to keep support for dynamic properties on stdClass, > > and if we do so, I would expect that to apply to subclasses as well. > > Does that actually follow, though? Right now, there is no advantage to > extending stdClass, so no reason to expect existing code to do so, and > no reason for people doing so to expect it to affect behaviour. > > > > Second, I consider "extends stdClass" to be something of a last-ditch > > option. If you encounter a dynamic property deprecation warning, you > > should generally resolve it in some other way, and only fall back to > > "extends stdClass" as the final option. > > > That's a reasonable argument in terms of the multiple inheritance case. > > My concern about the name remains though: people already do get confused > by the name "stdClass", because it's not in any way "standard", and > tells you nothing about what it does. > > Reading "class Foo extends stdClass" gives the reader no clues what > magic behaviour is being inherited; "class Foo extends DynamicObject" > would be much more clear. Similarly, "$foo = new DynamicObject; > $foo->bar = 42;" is clearer than "$foo = new stdClass; $foo->bar = 42;" > > Regards, > > -- > Rowan Tommins > [IMSoP] > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: https://www.php.net/unsub.php > > Please don't do this. Call it bad coding practices or not, but this was
something I've considered a feature of PHP and have actually built things around it. It's not something that can be easily refactored since it was part of the design. -- Chase Peeler chasepeeler@gmail.com
  115836
August 25, 2021 20:56 ramsey@php.net (Ben Ramsey)
--9T0kEoBqncr6QLdj4opjFb23AIhnDfYXp
Content-Type: text/plain; charset=utf-8
Content-Language: en-US
Content-Transfer-Encoding: quoted-printable

Chase Peeler wrote on 8/25/21 09:04:
> Please don't do this. Call it bad coding practices or not, but this was=
> something I've considered a feature of PHP and have actually built thin= gs
> around it. It's not something that can be easily refactored since it wa= s
> part of the design.
Since the stdClass behavior is retained in this proposal, could you change your base classes to `extend stdClass`? Cheers, Ben --9T0kEoBqncr6QLdj4opjFb23AIhnDfYXp--
  115840
August 25, 2021 22:37 mike@newclarity.net (Mike Schinkel)
> On Aug 25, 2021, at 10:04 AM, Chase Peeler <chasepeeler@gmail.com> wrote: > > On Wed, Aug 25, 2021 at 9:51 AM Rowan Tommins collins@gmail.com> > wrote: > >> On 25/08/2021 13:45, Nikita Popov wrote: >> >>> We obviously need to keep support for dynamic properties on stdClass, >>> and if we do so, I would expect that to apply to subclasses as well. >> >> Does that actually follow, though? Right now, there is no advantage to >> extending stdClass, so no reason to expect existing code to do so, and >> no reason for people doing so to expect it to affect behaviour. >> >> >>> Second, I consider "extends stdClass" to be something of a last-ditch >>> option. If you encounter a dynamic property deprecation warning, you >>> should generally resolve it in some other way, and only fall back to >>> "extends stdClass" as the final option. >> >> >> That's a reasonable argument in terms of the multiple inheritance case. >> >> My concern about the name remains though: people already do get confused >> by the name "stdClass", because it's not in any way "standard", and >> tells you nothing about what it does. >> >> Reading "class Foo extends stdClass" gives the reader no clues what >> magic behaviour is being inherited; "class Foo extends DynamicObject" >> would be much more clear. Similarly, "$foo = new DynamicObject; >> $foo->bar = 42;" is clearer than "$foo = new stdClass; $foo->bar = 42;" >> >> Regards, >> >> -- >> Rowan Tommins >> [IMSoP] >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: https://www.php.net/unsub.php >> >> > Please don't do this. Call it bad coding practices or not, but this was > something I've considered a feature of PHP and have actually built things > around it. It's not something that can be easily refactored since it was > part of the design.
While I tend to really object to BC breakage, when I saw this proposal I was all for it because it disallows a practice that I have seen used all too often in cases where there was no good reason to not declare the properties, and I know that to be fact because the cases I am referring to are ones where I refactored to use declared properties. That said, I'd be really interested in seeing use-cases where having dynamic properties is essential to an architecture and where it could not be easily refactored. I cannot envision any, but I am sure that I am just limited by the extent of my vision and so would like to know what those use-cases would be. --------- Speaking of, it would seem like if dynamic properties were to be deprecated PHP should also add a function that would allow registering a callable as global hook to be called every time ANY object has a property dynamically accessed or assigned — conceptually like how spl_autoload_register() works — so that developers could run their programs to see what properties are used. The hook could collect class names, property names and data types to help developers who need to update their code discover the information required for their class declarations. Because doing it manually is a real PITA. As would be adding __get()/__set() to every class when you have lots of classes and you'd need to delete all that code later anyway. -Mike
  115814
August 25, 2021 14:08 pierre-php@processus.org (Pierre)
Le 25/08/2021 à 15:51, Rowan Tommins a écrit :
> On 25/08/2021 13:45, Nikita Popov wrote: > >> We obviously need to keep support for dynamic properties on stdClass, >> and if we do so, I would expect that to apply to subclasses as well. > > Does that actually follow, though? Right now, there is no advantage to > extending stdClass, so no reason to expect existing code to do so, and > no reason for people doing so to expect it to affect behaviour. > > >> Second, I consider "extends stdClass" to be something of a last-ditch >> option. If you encounter a dynamic property deprecation warning, you >> should generally resolve it in some other way, and only fall back to >> "extends stdClass" as the final option. > > > That's a reasonable argument in terms of the multiple inheritance case. > > My concern about the name remains though: people already do get > confused by the name "stdClass", because it's not in any way > "standard", and tells you nothing about what it does. > > Reading "class Foo extends stdClass" gives the reader no clues what > magic behaviour is being inherited; "class Foo extends DynamicObject" > would be much more clear. Similarly, "$foo = new DynamicObject; > $foo->bar = 42;" is clearer than "$foo = new stdClass; $foo->bar = 42;" > > Regards, > Hello,
And why not adding an extra keyword, such as: ``` ``` Regards, -- Pierre
  115815
August 25, 2021 14:18 internals@lists.php.net ("Levi Morrison via internals")
> And why not adding an extra keyword, such as: > > ``` > dynamic class Foo { } // Dynamic allowed > class Bar {} // Dynamic disallowed > ?> > ```
I am opposed. IMO it's not worth adding anything to the language to preserve this existing behavior other than allowing `__get`/`__set`, etc, which already exist for this purpose. Additionally, there are technical benefits to removing dynamic properties altogether, so I don't think we should "half" remove it. See https://wiki.php.net/rfc/deprecate_dynamic_properties#internal_impact.
  115803
August 25, 2021 10:52 denis@mobilejoomla.com (Denis Ryabov)
On 25.08.2021 13:02, Nikita Popov wrote:
> Hi internals, > > I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > This has been discussed in various forms in the past, e.g. in > https://wiki.php.net/rfc/locked-classes as a class modifier and > https://wiki.php.net/rfc/namespace_scoped_declares / > https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md > as a declare directive. > > This RFC takes the more direct route of deprecating this functionality > entirely. I expect that this will have relatively little impact on modern > code (e.g. in Symfony I could fix the vast majority of deprecation warnings > with a three-line diff), but may have a big impact on legacy code that > doesn't declare properties at all. > > Regards, > Nikita
I use dynamical properties in a legacy code for lazy object creation in the dependency container (with properties declared using @property phpDoc comment, so that PhpStorm IDE supports them). But in my case it's not a problem to refactor that code. I'd suggest to consider "use stdClassTrait" (the name is just for example) as an alternative to "extends stdClass" and "implements stdClassInterface", because 1) It allows to further implement __get/__set in that trait, and 2) It's possible to don't require base abstract class to extend stdClass when dynamical properties are used in a child class only.
  115805
August 25, 2021 10:55 ocramius@gmail.com (Marco Pivetta)
Hey Nikita

On Wed, Aug 25, 2021 at 12:03 PM Nikita Popov ppv@gmail.com> wrote:

> Hi internals, > > I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > This has been discussed in various forms in the past, e.g. in > https://wiki.php.net/rfc/locked-classes as a class modifier and > https://wiki.php.net/rfc/namespace_scoped_declares / > > https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md > as a declare directive. > > This RFC takes the more direct route of deprecating this functionality > entirely. I expect that this will have relatively little impact on modern > code (e.g. in Symfony I could fix the vast majority of deprecation warnings > with a three-line diff), but may have a big impact on legacy code that > doesn't declare properties at all. >
I'm totally on board with this! Others in the thread have mentioned that these dynamic properties can be used for lazy-loading purposes, but I think we've demonstrated (over the years) that this can be achieved in a type-safe way anyway, and dynamic properties are not needed at all. Over the past decade, I've not seen a single valid use of dynamic properties either. If this passes, I'll also deprecate and discontinue experiments like https://github.com/Ocramius/LazyProperty Greets, Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/
  115807
August 25, 2021 11:28 ayesh@php.watch (Ayesh Karunaratne)
> > Hi internals, > > I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > This has been discussed in various forms in the past, e.g. in > https://wiki.php.net/rfc/locked-classes as a class modifier and > https://wiki.php.net/rfc/namespace_scoped_declares / > https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md > as a declare directive. > > This RFC takes the more direct route of deprecating this functionality > entirely. I expect that this will have relatively little impact on modern > code (e.g. in Symfony I could fix the vast majority of deprecation warnings > with a three-line diff), but may have a big impact on legacy code that > doesn't declare properties at all. > > Regards, > Nikita
Hi Nikita, Thanks for opening this, I'm very supportive of this. Having some Drupal and other legacy background, I'm afraid this could disrupt a lot of Drupal applications, which uses dynamic properties quite extensively in its Entity APIs, Views, etc. I totally agree that it is a bad practice, but that's what half a million or so Drupal 7 web sites do. Perhaps, we can make it an easy to opt-in with a keyword (`locked class Foo {}`) or an interface (`Foo implements LockedClass {}`), or provide an easy opt-out (similar to the tentative return type attribute)? Thank you, Ayesh.
  115808
August 25, 2021 11:29 internals@lists.php.net ("Björn Larsson via internals")
Den 2021-08-25 kl. 12:02, skrev Nikita Popov:
> Hi internals, > > I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > This has been discussed in various forms in the past, e.g. in > https://wiki.php.net/rfc/locked-classes as a class modifier and > https://wiki.php.net/rfc/namespace_scoped_declares / > https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md > as a declare directive. > > This RFC takes the more direct route of deprecating this functionality > entirely. I expect that this will have relatively little impact on modern > code (e.g. in Symfony I could fix the vast majority of deprecation warnings > with a three-line diff), but may have a big impact on legacy code that > doesn't declare properties at all. > > Regards, > Nikita > I'm in favour of the proposal as long as the stdClass is leaved as is!
For declared classes I think it's a good idea. We have legacy code that is littered with dynamic properties using stdClass. It runs today on PHP 7.4.22 and we plan to migrate to PHP 8 as soon as some Open source libraries works under PHP 8. Being forced to rewrite this if this proposal changes to also disallow stdClass dynamic properties would have zero benefits for the app itself and only incur a cost. Regards //Björn L
  115816
August 25, 2021 14:26 tysonandre775@hotmail.com (tyson andre)
Hi Nikita Popov,

> I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > This has been discussed in various forms in the past, e.g. in > https://wiki.php.net/rfc/locked-classes as a class modifier and > https://wiki.php.net/rfc/namespace_scoped_declares / > https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md > as a declare directive. > > This RFC takes the more direct route of deprecating this functionality > entirely. I expect that this will have relatively little impact on modern > code (e.g. in Symfony I could fix the vast majority of deprecation warnings > with a three-line diff), but may have a big impact on legacy code that > doesn't declare properties at all.
I'd had some concerns. It might be too soon after your addition of WeakMap. https://www.php.net/weakmap was introduced in PHP 8.0 (and WeakReference in 7.4), so applications/libraries fixing the deprecation may need to drop support for php 7.x early. Applications attempting to polyfill a WeakMap in earlier PHP versions would potentially leak a lot of memory in php 7.x. - I don't know how many minor versions to expect before 9.0 is out - Is it feasible for a developer to create a native PECL polyfill for WeakMap for earlier PHP versions that has a subset of the functionality the native weak reference counting does? (e.g. to only free polyfilled weak references when cyclic garbage collection is triggered and the reference count is 1). Additionally, it makes it less efficient (but still feasible) to associate additional fields with libraries or native classes/PECLs you don't own (especially for circular data structures), especially if they need to be serialized later. (it isn't possible to serialize WeakMap, and the WeakMap would have fields unrelated to the data being serialized) I guess you can have a wrapper class that iterates over a WeakMap to capture and serialize the values that still exist in SplObjectStorage, though. (Though other languages do just fine without this functionality) I'm not sure if a library owner would want to change their class hierarchy to extend stdClass (to avoid changing the behavior of anything using `$x instanceof stdClass`) and the attribute/trait approach might be more acceptable to library owners. E.g. https://github.com/vimeo/psalm/blob/master/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php would set a dynamic property `$stmt->pure` in `PhpParser\Node\Expr\FuncCall $stmt` in a vendor dependency on php-parser. Regards, Tyson
  115817
August 25, 2021 14:49 nikita.ppv@gmail.com (Nikita Popov)
On Wed, Aug 25, 2021 at 4:26 PM tyson andre <tysonandre775@hotmail.com>
wrote:

> Hi Nikita Popov, > > > I'd like to propose the deprecation of "dynamic properties", that is > > properties that have not been declared in the class (stdClass and > > __get/__set excluded, of course): > > > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > > > This has been discussed in various forms in the past, e.g. in > > https://wiki.php.net/rfc/locked-classes as a class modifier and > > https://wiki.php.net/rfc/namespace_scoped_declares / > > > https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md > > as a declare directive. > > > > This RFC takes the more direct route of deprecating this functionality > > entirely. I expect that this will have relatively little impact on modern > > code (e.g. in Symfony I could fix the vast majority of deprecation > warnings > > with a three-line diff), but may have a big impact on legacy code that > > doesn't declare properties at all. > > I'd had some concerns. > > It might be too soon after your addition of WeakMap. > https://www.php.net/weakmap was introduced in PHP 8.0 (and WeakReference > in 7.4), > so applications/libraries fixing the deprecation may need to drop support > for php 7.x early. > Applications attempting to polyfill a WeakMap in earlier PHP versions > would potentially leak a lot of memory in php 7.x. > > - I don't know how many minor versions to expect before 9.0 is out > - Is it feasible for a developer to create a native PECL polyfill for > WeakMap for earlier PHP versions that has a > subset of the functionality the native weak reference counting does? > (e.g. to only free polyfilled weak references when cyclic garbage > collection is triggered and the reference count is 1). >
For compatibility with < PHP 7.4 in this use case I'd suggest to either suppress the deprecation for a particular assignment, or to pick the used mechanism depending on PHP version. We don't have an official schedule for major versions, but going by the last few releases, I'd guess that it happens after PHP 8.4, or around that time :) I think an approximate PECL polyfill (that tries to free on GC) would be possible, but I'm not sure it would really be useful relative to having version-dependent behavior.
> Additionally, it makes it less efficient (but still feasible) to associate > additional fields > with libraries or native classes/PECLs you don't own (especially for > circular data structures), especially if they need to be serialized later. >
Efficiency probably depends on the case here -- while I'd expect the dynamic property to be more efficient on access than the WeakMap, it will likely also use more memory, sometimes much more.
> (it isn't possible to serialize WeakMap, and the WeakMap would have fields > unrelated to the data being serialized) > I guess you can have a wrapper class that iterates over a WeakMap to > capture and serialize the values that still exist in SplObjectStorage, > though. > (Though other languages do just fine without this functionality) >
Right, the WeakMap approach will not impact the serialization of the object, as well as other property based behaviors, such as comparison semantics. I would usually count that as an advantage (what you do shouldn't impact the behavior of 3rd-party classes), but there's probably use cases for everything :)
> I'm not sure if a library owner would want to change their class hierarchy > to extend stdClass (to avoid changing the behavior of anything using `$x > instanceof stdClass`) and the attribute/trait approach might be more > acceptable to library owners. > E.g. > https://github.com/vimeo/psalm/blob/master/src/Psalm/Internal/Analyzer/Statements/Expression/Call/FunctionCallAnalyzer.php > would set a dynamic property `$stmt->pure` in > `PhpParser\Node\Expr\FuncCall $stmt` in a vendor dependency on php-parser. >
I wouldn't want library authors to change their class hierarchy for 3rd-party use cases, unless those use cases are actually fundamental to the library in some way. For PHP-Parser this is actually the case, which is why it offers the Node::setAttribute() API. The intended way to do this would be $stmt->setAttribute('pure', true) in this case. Regards, Nikita
  115819
August 25, 2021 15:28 pollita@php.net (Sara Golemon)
On Wed, Aug 25, 2021 at 5:03 AM Nikita Popov ppv@gmail.com> wrote:
> I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties >
> This RFC offers `extends stdClass` as a way to opt-in to the use of dynamic properties.
> This makes the assumption that existing uses of dynamic properties are all
root classes. I don't think that assumption can be made.
> Some people have suggested that we could use a magic marker > interface (implements SupportsDynamicProperties), > an attribute (#[SupportsDynamicProperties]) > or a trait (use DynamicProperties;) instead. > My gut-check says an Attribute works well enough. This will unlock the
class (disable deprecation warning) in 8.2+ and be ignored in earlier releases (8.0 and 8.1 would need an auto-loaded polyfill userspace attribute obviously, but that's a tractable problem). #[SupportsDynamicProperties] class Foo { ... }
> The Locked classes RFC took an alternative approach to this problem space: > Rather than deprecating/removing dynamic properties and providing an opt-in
> for specific classes, it instead allowed marking specific classes as locked in
> order to forbid creation of dynamic properties on them. > > I don't believe that this is the right strategy, because in contemporary code,
> classes being “locked” is the default state, while classes that require dynamic
> properties are a rare exception. Additionally, this requires that class owners
> (which may be 3rd party packages) consistently add the “locked” keyword > to be effective. > I struggle here, because the opt-in approach is the most BC, but I actually
think you're right. I think[citation needed] that dynamic props are probably rare enough that as long as the escape hatch is clear, we can be a little more bold about nudging the ecosystem forward. I will counter however, that the same issue with 3rd party libraries applies to opt-out as opt-in. A third party library that's undermaintained (and uses dynamic props) won't be able to be used out of the box once we apply this. I don't think that's enough to scare us off, it just means that the opt-in side of that argument cancels out. -Sara
  115820
August 25, 2021 16:05 larry@garfieldtech.com ("Larry Garfield")
On Wed, Aug 25, 2021, at 10:28 AM, Sara Golemon wrote:
> On Wed, Aug 25, 2021 at 5:03 AM Nikita Popov ppv@gmail.com> wrote: > > I'd like to propose the deprecation of "dynamic properties", that is > > properties that have not been declared in the class (stdClass and > > __get/__set excluded, of course): > > > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > > > > This RFC offers `extends stdClass` as a way to opt-in to the use of > dynamic properties. > > > This makes the assumption that existing uses of dynamic properties are all > root classes. I don't think that assumption can be made. > > > Some people have suggested that we could use a magic marker > > interface (implements SupportsDynamicProperties), > > an attribute (#[SupportsDynamicProperties]) > > or a trait (use DynamicProperties;) instead. > > > My gut-check says an Attribute works well enough. This will unlock the > class (disable deprecation warning) in 8.2+ and be ignored in earlier > releases (8.0 and 8.1 would need an auto-loaded polyfill userspace > attribute obviously, but that's a tractable problem). > > #[SupportsDynamicProperties] > class Foo { ... } > > > The Locked classes RFC took an alternative approach to this problem space: > > Rather than deprecating/removing dynamic properties and providing an > opt-in > > for specific classes, it instead allowed marking specific classes as > locked in > > order to forbid creation of dynamic properties on them. > > > > I don't believe that this is the right strategy, because in contemporary > code, > > classes being “locked” is the default state, while classes that require > dynamic > > properties are a rare exception. Additionally, this requires that class > owners > > (which may be 3rd party packages) consistently add the “locked” keyword > > to be effective. > > > I struggle here, because the opt-in approach is the most BC, but I actually > think you're right. I think[citation needed] that dynamic props are > probably rare enough that as long as the escape hatch is clear, we can be a > little more bold about nudging the ecosystem forward. I will counter > however, that the same issue with 3rd party libraries applies to opt-out as > opt-in. A third party library that's undermaintained (and uses dynamic > props) won't be able to be used out of the box once we apply this. I don't > think that's enough to scare us off, it just means that the opt-in side of > that argument cancels out. > > -Sara
I am overall in favor of this move and making declared-only the default. What I'm still undecided on is what escape hatch should be allowed. I agree that "you can extend stdClass already" isn't a good one, because that isn't viable in many cases. The most viable options in my mind are "use __get/__set yourself, you heathen" and an attribute. The benefit of an attribute over an interface or new parent class is that it's silently backward compatible, especially since attributes are comments in <8.0 versions, so legacy code can add that marker and still be compatible with anything from 5.0 on. The "internal impact" section makes me lean toward the "__get/__set" option, but I don't fully understand the benefits of the impact. It seems it would make the engine a little tidier and more efficient, but I don't have a good sense for how much more efficient, which would need to be balanced against how much more INefficient user-space code with dynamic properties would become. (Either using __get/__set itself, or inheriting from a future stdClass that implements them internally.) IMO we should prioritize engine efficiency over edge-case efficiency (which dynamic properties are these days), but the amount still matters. I'm currently working on some improvements to the FIG to allow it to release small, incomplete code libraries or shared type libraries. Perhaps a fully user-space BC trait with the basic behavior (basically what's shown in the RFC) could live there? (Not speaking on FIG's behalf, here, just musing aloud.) --Larry Garfield
  115837
August 25, 2021 21:02 ramsey@php.net (Ben Ramsey)
--oGolVVusa5BmXiFJpZwc3PyaAUAQb3TQ5
Content-Type: text/plain; charset=utf-8
Content-Language: en-US
Content-Transfer-Encoding: quoted-printable

Sara Golemon wrote on 8/25/21 10:28:
> My gut-check says an Attribute works well enough. This will unlock the=
> class (disable deprecation warning) in 8.2+ and be ignored in earlier > releases (8.0 and 8.1 would need an auto-loaded polyfill userspace > attribute obviously, but that's a tractable problem). >=20 > #[SupportsDynamicProperties] > class Foo { ... }
I like this approach.
> I struggle here, because the opt-in approach is the most BC, but I actu= ally
> think you're right. I think[citation needed] that dynamic props are > probably rare enough that as long as the escape hatch is clear, we can = be a
> little more bold about nudging the ecosystem forward. I'd feel better about this if we had that citation. In modern code, I
agree they are probably rare, but I think there's a lot of legacy code that makes heavy use of dynamic properties as an important feature of PHP. (I'm working on one such project right now.) Cheers, Ben --oGolVVusa5BmXiFJpZwc3PyaAUAQb3TQ5--
  115848
August 26, 2021 08:34 nikita.ppv@gmail.com (Nikita Popov)
On Wed, Aug 25, 2021 at 5:28 PM Sara Golemon <pollita@php.net> wrote:

> On Wed, Aug 25, 2021 at 5:03 AM Nikita Popov ppv@gmail.com> wrote: > > I'd like to propose the deprecation of "dynamic properties", that is > > properties that have not been declared in the class (stdClass and > > __get/__set excluded, of course): > > > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > > > > This RFC offers `extends stdClass` as a way to opt-in to the use of > dynamic properties. > > > This makes the assumption that existing uses of dynamic properties are all > root classes. I don't think that assumption can be made. > > > Some people have suggested that we could use a magic marker > > interface (implements SupportsDynamicProperties), > > an attribute (#[SupportsDynamicProperties]) > > or a trait (use DynamicProperties;) instead. > > > My gut-check says an Attribute works well enough. This will unlock the > class (disable deprecation warning) in 8.2+ and be ignored in earlier > releases (8.0 and 8.1 would need an auto-loaded polyfill userspace > attribute obviously, but that's a tractable problem). > > #[SupportsDynamicProperties] > class Foo { ... } >
The crux of the issue is what our end goal is: 1. Require users to explicitly annotate classes that use dynamic properties, but otherwise keep dynamic properties as a fully supported part of the core language. 2. Remove support for dynamic properties entirely. The core language only has declared properties and __get/__set, and nothing else. stdClass is just a very efficient implementation of __get/__set. The RFC is currently written under the assumption that the end goal is (2). To support that, I believe that "extends stdClass" and "use DynamicProperties" are the only viable approaches. The former, because it inherits stdClass behavior, the latter because it's literally __get/__set. An attribute would require retaining the capability to have arbitrary classes with dynamic properties. Now, if the actual goal is (1) instead, then I fully agree that using a #[SupportsDynamicProperties] attribute is the ideal solution. It can be easily applied anywhere and has no BC concerns. Heck, someone who just doesn't care could easily slap it on their whole codebase without spending brain cycles on more appropriate solutions. I do think that just (1) by itself would already be very worthwhile. If that's all we can reasonably target, then I'd be fine with the #[SupportsDynamicProperties] solution. Though if (2) is viable without too many complications, then I think that would be the better final state to reach.
> > The Locked classes RFC took an alternative approach to this problem > space: > > Rather than deprecating/removing dynamic properties and providing an > opt-in > > for specific classes, it instead allowed marking specific classes as > locked in > > order to forbid creation of dynamic properties on them. > > > > I don't believe that this is the right strategy, because in contemporary > code, > > classes being “locked” is the default state, while classes that require > dynamic > > properties are a rare exception. Additionally, this requires that class > owners > > (which may be 3rd party packages) consistently add the “locked” keyword > > to be effective. > > > I struggle here, because the opt-in approach is the most BC, but I > actually think you're right. I think[citation needed] that dynamic props > are probably rare enough that as long as the escape hatch is clear, we can > be a little more bold about nudging the ecosystem forward. I will counter > however, that the same issue with 3rd party libraries applies to opt-out as > opt-in. A third party library that's undermaintained (and uses dynamic > props) won't be able to be used out of the box once we apply this. I don't > think that's enough to scare us off, it just means that the opt-in side of > that argument cancels out. >
I think the argument isn't quite symmetric: A 3rd-party library in maintenance-only mode has essentially no incentive to go out of their way and add a "locked" keyword/attribute to their classes. Adding some missing property declarations to keep working on new PHP versions is a different matter. Regards, Nikita
  115871
August 26, 2021 22:10 smalyshev@gmail.com (Stanislav Malyshev)
Hi!

> The crux of the issue is what our end goal is: > > 1. Require users to explicitly annotate classes that use dynamic > properties, but otherwise keep dynamic properties as a fully supported part > of the core language. > 2. Remove support for dynamic properties entirely. The core language only > has declared properties and __get/__set, and nothing else. stdClass is just > a very efficient implementation of __get/__set.
I think goal (1) is reasonable for the long run, and goal (2) is taking it a bit too far for PHP. -- Stas Malyshev smalyshev@gmail.com
  115874
August 27, 2021 03:02 pierre.php@gmail.com (Pierre Joye)
Hi Stan,

On Fri, Aug 27, 2021 at 5:10 AM Stanislav Malyshev <smalyshev@gmail.com> wrote:
> > Hi! > > > The crux of the issue is what our end goal is: > > > > 1. Require users to explicitly annotate classes that use dynamic > > properties, but otherwise keep dynamic properties as a fully supported part > > of the core language. > > 2. Remove support for dynamic properties entirely. The core language only > > has declared properties and __get/__set, and nothing else. stdClass is just > > a very efficient implementation of __get/__set. > > I think goal (1) is reasonable for the long run, and goal (2) is taking > it a bit too far for PHP.
I feel the same way. However my gut feeling tells me that we will end up with (2) sooner or later. Having StdClass behaving differently (even if it is technically not, I don't think the "it is a more efficient get/set implementation" will make it through our users base) looks inconsistent. I don't know how others feel about it, I think most want to go the path to (2) and a more strict, if not almost fully strict PHP. Core devs to simplify the engine, users to allow them easier checks and safety in their frameworks or libs. End user don't really bother as far as I can see. We may have to decide once the long term vision for PHP and then do the changes accordingly, and more importantly, with consistency. Best, -- Pierre @pierrejoye | http://www.libgd.org
  115875
August 27, 2021 03:56 tobias.nyholm@gmail.com (Tobias Nyholm)
Just giving my 2 cents: 

> 2. Remove support for dynamic properties entirely.
I support this RFC and I like the end goal to be to remove the dynamic properties entirely. Dynamic properties are just confusing for beginners. “This is how you declare properties, the scope, the type, name etc.. but you don’t have too…” I also remember that I’ve fixed more than one bug because I misspelled a property name. I understand there will be an impact on legacy code but there is help to find dynamic properties (static analysers) and there is also a clear upgrade path. // Tobias
  115876
August 27, 2021 05:19 mike@newclarity.net (Mike Schinkel)
> On Aug 26, 2021, at 11:02 PM, Pierre Joye php@gmail.com> wrote: > I don't know how others feel about it, I think most want to go the > path to (2) and a more strict, if not almost fully strict PHP. Core > devs to simplify the engine, users to allow them easier checks and > safety in their frameworks or libs. End user don't really bother as > far as I can see. We may have to decide once the long term vision for > PHP and then do the changes accordingly, and more importantly, with > consistency.
I tend to concur that path (2) would provide the better outcome. However, eliminating dynamic variables would be eliminating the ability to simulate a(t least one) language feature that some (many?) people have been using dynamic variables to simulate. Maybe as part of deprecation of dynamic variables we should also consider adding this(ese) feature(s) to the PHP language? There are two approaches I can envision, Both would better enable the S.O.L.I.D. "open-closed" principle in PHP. 1.) Allow PHP class declaration across multiple files — A use-case for this is what I think is effectively the command dispatcher pattern where properties contain instances of classes that might be contributed by 3rd party code to allow those developers to access the instances by named property: e.g. $cms->map->display() where $map is added by a 3rd party library to the class for the $cms instance before $cms is instantiated. See: https://gist.github.com/mikeschinkel/ed4f9594c105dae7371bfce413399948 Some might view this as "monkey patching" but I view it as a more structured approach, like C# partial classes. 2.) Allow trait usage for a class from another file — This is just a slightly different spin on #1. See: https://gist.github.com/mikeschinkel/5b433532dc54adf53f5b239c8086fd63 Each approach has its own pros and cons but it probably depends on which would be easier and more performant to implement. -Mike
  115872
August 27, 2021 01:19 pollita@php.net (Sara Golemon)
On Thu, Aug 26, 2021 at 3:34 AM Nikita Popov ppv@gmail.com> wrote:
> > The crux of the issue is what our end goal is: > > 1. Require users to explicitly annotate classes that use dynamic properties,
> but otherwise keep dynamic properties as a fully supported part of the core language.
> That's how I initially read your RFC, what I'm hearing here is that your
quite explicit goal is:
> 2. Remove support for dynamic properties entirely. The core language only has
> declared properties and __get/__set, and nothing else. stdClass is just a very
> efficient implementation of __get/__set. > If that's your position, then the `extends stdClass` approach makes sense,
because the dynamic properties HashTable can live in the object's extra data offset block and the get_prop/set_prop implementations in stdClass' handlers are the *only* things which know about dynamic properties. That represents a significant advantage to the engine for the "happy path" of declared properties only. Every (non-dynamic) object is a word (8 bytes) leaner, and the branch points for dynamic property access are limited to the only place they can be used, and where the typical result is positive. Starting from that argument, your RFC begins to look more compelling. I was definitely not starting there on an initial read. I do still have reservations about enforcing stdClass as a root for any class which wants to use dynamic properties. It's messy, but... to paraphrase what you said about going with an attribute approach... yeah, someone could make every current root class in their application explicitly inherit from stdClass without any ill effects in PHP < 8.2, with only the exception of external libraries being a problem. So that's the spectrum: - Opt-in to strict behavior: No BC impact, least benefit to the ecosystem or the engine - Attribute/Interface opt-out (goal#1): Moderate BC impact, ecosystem benefits well, engine benefits a little, but not much. - Extend stdClass opt-out (goal#2): Highest BC impact, ecosystem and engine benefit most. Goal#2 is bold. Possibly not-too-bold, but it's not clear to me where dynamic props are being used today and how many of those places can't "just extend stdClass" for one reason or another. Goal#1 might be a stepping stone along the way to Goal#2, as it will give us something clear to scan for across major frameworks at the very least, but that is going to push us from removal in 9.0 all the way out to removal in 10.0. If you're keeping track, that's gonna be circa 2030 give or take a year or two. That might be dangling the carrot out a little too far... The purist in me wants to be bold. It also wants some hard data on existing usages. A simple grep isn't going to cut it this time. We're going to need to run some static analyzers on some frameworks and libraries. Who's got it in them to do the research? -Sara
  115873
August 27, 2021 02:02 matthewmatthew@gmail.com (Matthew Brown)
On Thu, 26 Aug 2021 at 21:20, Sara Golemon <pollita@php.net> wrote:

> We're > going to need to run some static analyzers on some frameworks and > libraries. Who's got it in them to do the research? > > -Sara >
I'm not volunteering, but I forked Nikita's package analysis to add Psalm scanning a while ago: https://github.com/muglug/popular-package-analysis It's not trivial (downloading the requisite files takes up a lot of HDD space) but Psalm's output can be parsed and analysed looking for UndefinedPropertyFetch and UndefinedThisPropertyFetch issues.
  115839
August 25, 2021 22:05 paul.crovella@gmail.com (Paul Crovella)
On Wed, Aug 25, 2021 at 3:03 AM Nikita Popov ppv@gmail.com> wrote:
> > Hi internals, > > I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > This has been discussed in various forms in the past, e.g. in > https://wiki.php.net/rfc/locked-classes as a class modifier and > https://wiki.php.net/rfc/namespace_scoped_declares / > https://github.com/nikic/php-rfcs/blob/language-evolution/rfcs/0000-language-evolution.md > as a declare directive. > > This RFC takes the more direct route of deprecating this functionality > entirely. I expect that this will have relatively little impact on modern > code (e.g. in Symfony I could fix the vast majority of deprecation warnings > with a three-line diff), but may have a big impact on legacy code that > doesn't declare properties at all. > > Regards, > Nikita
I'd like to see a section (or just a paragraph) in the RFC summarizing the benefits of making this change. Right now the introduction says that using dynamic properties in modern code "is rarely done intentionally" implying that it's typically done unintentionally, however I can't remember the last time I saw unintentional use either. Is this a common cause of bugs? The internal impact section mentions saving 8 bytes per object plus an unspecified "dramatic" amount for an object iterated over via `foreach` which sounds nice but leaves me guesstimating at real-world impact. I don't much care for dynamic properties, but I also don't much see them outside legacy code so they're not bringing me troubles either. Breaking working code, however, would.
  115841
August 25, 2021 22:47 the.liquid.metal@gmail.com (Hendra Gunawan)
Hi.

A chunk in the RFC:

    abstract class Constraint {
        public $groups;

        public function __construct() {
            unset($this->groups);
        }

        public function __get($name) {
            // Will get called on first access, but once initialized.
            $this->groups = ...;
        }
    }

Interesting! new to me.

Maybe someday we will have this one:

    abstract class Constraint {
        public lazy $groups;

        public function __construct() {
            // no need to do this:
            // unset($this->groups);
        }

        public function __get($name) {
            // Will get called on first access, but once initialized.
            $this->groups = ...;
        }
    }

Regards,
Hendra Gunawan.
  115895
August 30, 2021 12:13 come.chilliet@fusiondirectory.org (=?UTF-8?B?Q8O0bWU=?= Chilliet)
Le Wed, 25 Aug 2021 12:02:49 +0200,
Nikita Popov ppv@gmail.com> a écrit :
> Hi internals, > > I'd like to propose the deprecation of "dynamic properties", that is > properties that have not been declared in the class (stdClass and > __get/__set excluded, of course): > > https://wiki.php.net/rfc/deprecate_dynamic_properties
If I understand correctly the RFC, in these two classes: class A { public $prop; public function __construct() { unset($this->prop); } } class B { public $prop; } The property $prop is not in the same state in the end? What is the difference? isset returns FALSE for both, no? And property_exists? Is it something that was the same before the RFC and would be different after, or is it already two different cases and how? Côme
  115896
August 30, 2021 12:37 nikita.ppv@gmail.com (Nikita Popov)
On Mon, Aug 30, 2021 at 2:14 PM Côme Chilliet <
come.chilliet@fusiondirectory.org> wrote:

> Le Wed, 25 Aug 2021 12:02:49 +0200, > Nikita Popov ppv@gmail.com> a écrit : > > Hi internals, > > > > I'd like to propose the deprecation of "dynamic properties", that is > > properties that have not been declared in the class (stdClass and > > __get/__set excluded, of course): > > > > https://wiki.php.net/rfc/deprecate_dynamic_properties > > If I understand correctly the RFC, in these two classes: > > class A { > public $prop; > > public function __construct() { > unset($this->prop); > } > } > > class B { > public $prop; > } > > The property $prop is not in the same state in the end? What is the > difference? > isset returns FALSE for both, no? And property_exists? >
In the latter case, the property has value null. In the former case, it is unset. In both cases, it is declared. Accessing an unset property will trigger __get/__set. Accessing a null property will not (assuming it is visible). Is it something that was the same before the RFC and would be different
> after, > or is it already two different cases and how?
This RFC does not have any impact on this behavior. This is a "standard" pattern used for lazy initialization. Regards, Nikita