On Wed, Aug 25, 2021 at 12:45 PM Rowan Tommins <rowan.coll...@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

Reply via email to