Add get_mangled_object_properties()

  105697
May 14, 2019 12:38 nikita.ppv@gmail.com (Nikita Popov)
Hi internals,

Inspired by the recent discussion on __toArray(), I'd like to propose the
addition of a get_mangled_object_properties() function, implemented in
https://github.com/php/php-src/pull/4163.

This function returns the mangled object properties (duh...), which matches
the behavior of the (array) cast, with the difference that an overloaded
(array) cast will be ignored. To the best of my knowledge the only internal
class currently doing this is ArrayObject.

There are a couple of motivation for this:
1. It makes it more obvious that code operates on mangled properties. This
allows clearly distinguishing (array) casts used for low-level object
introspection and (array) casts used for things like converting between
stdClass and arrays.
2. It is more robust, because it is not affected by overloading. At least
in theory it allows us to introduce the __toArray() method proposed in the
other thread (though I don't personally endorse this).
3. Longer term, it would allow us to change (array) to return non-mangled
(visibility-respecting) properties -- the current behavior is a WTF factor
for anyone who doesn't happen to work on serialization or dumping libraries.

Thoughts?

Regards,
Nikita
  105698
May 14, 2019 12:51 stevenwadejr@gmail.com (Steven Wade)
> Inspired by the recent discussion on __toArray(), I'd like to propose the > addition of a get_mangled_object_properties() function, implemented in > https://github.com/php/php-src/pull/4163. > > This function returns the mangled object properties (duh...), which matches > the behavior of the (array) cast, with the difference that an overloaded > (array) cast will be ignored. To the best of my knowledge the only internal > class currently doing this is ArrayObject. > > There are a couple of motivation for this: > 1. It makes it more obvious that code operates on mangled properties. This > allows clearly distinguishing (array) casts used for low-level object > introspection and (array) casts used for things like converting between > stdClass and arrays. > 2. It is more robust, because it is not affected by overloading. At least > in theory it allows us to introduce the __toArray() method proposed in the > other thread (though I don't personally endorse this). > 3. Longer term, it would allow us to change (array) to return non-mangled > (visibility-respecting) properties -- the current behavior is a WTF factor > for anyone who doesn't happen to work on serialization or dumping libraries. > > Thoughts? > > Regards, > Nikita
I think this is a great idea. Not just because I want __toArray() to succeed, but because some of the concerns raised by its discussions were mainly focused on the odd behavior that current array casting exhibits and possibly losing that. By introducing this new function, it can be a more appropriate method of gaining insight into a class' properties. I like the idea of renaming the function to "get_mangled_object_vars()" that was mentioned on the PR. It does bring it more in line with current naming schemes. -- Steven Wade stevenwadejr@gmail.com
  105701
May 14, 2019 14:29 benjamin.morel@gmail.com (Benjamin Morel)
I like the explicitness of the proposal, but only if performance is as good
as (array) cast. One of the reasons we use casting to array in libraries is
not only to access all properties at once, but also because it's fast as
it's implemented as an opcode and not a function call. Would this function
come with its own opcode, like strlen() / gettype() / etc.?

Ben
  105702
May 14, 2019 14:36 ocramius@gmail.com (Marco Pivetta)
On Tue, May 14, 2019 at 4:29 PM Benjamin Morel morel@gmail.com>
wrote:

> I like the explicitness of the proposal, but only if performance is as good > as (array) cast. One of the reasons we use casting to array in libraries is > not only to access all properties at once, but also because it's fast as > it's implemented as an opcode and not a function call. Would this function > come with its own opcode, like strlen() / gettype() / etc.? > > Ben >
Indeed. Besides that, this is a good chance to have an explicit `object` parameter type. @Nikic is the return type also `array`, according to reflection? Marco Pivetta http://twitter.com/Ocramius http://ocramius.github.com/
  105704
May 14, 2019 14:45 nikita.ppv@gmail.com (Nikita Popov)
On Tue, May 14, 2019 at 4:37 PM Marco Pivetta <ocramius@gmail.com> wrote:

> > On Tue, May 14, 2019 at 4:29 PM Benjamin Morel morel@gmail.com> > wrote: > >> I like the explicitness of the proposal, but only if performance is as >> good >> as (array) cast. One of the reasons we use casting to array in libraries >> is >> not only to access all properties at once, but also because it's fast as >> it's implemented as an opcode and not a function call. Would this function >> come with its own opcode, like strlen() / gettype() / etc.? >> >> Ben >> > > Indeed. Besides that, this is a good chance to have an explicit `object` > parameter type. > > @Nikic is the return type also `array`, according to reflection? >
I'd prefer not to add either of them until the question of type annotations on internal functions is solved more comprehensively in PHP 8. In particular adding an "object" type will currently add additional cost to the call. I hope that we'll solve this problem in PHP 8 and annotate functions with types in a comprehensive way (including existing functions, like get_object_vars). Nikita
  105843
June 6, 2019 07:52 nikita.ppv@gmail.com (Nikita Popov)
On Tue, May 14, 2019 at 4:45 PM Nikita Popov ppv@gmail.com> wrote:

> On Tue, May 14, 2019 at 4:37 PM Marco Pivetta <ocramius@gmail.com> wrote: > >> >> On Tue, May 14, 2019 at 4:29 PM Benjamin Morel morel@gmail.com> >> wrote: >> >>> I like the explicitness of the proposal, but only if performance is as >>> good >>> as (array) cast. One of the reasons we use casting to array in libraries >>> is >>> not only to access all properties at once, but also because it's fast as >>> it's implemented as an opcode and not a function call. Would this >>> function >>> come with its own opcode, like strlen() / gettype() / etc.? >>> >>> Ben >>> >> >> Indeed. Besides that, this is a good chance to have an explicit `object` >> parameter type. >> >> @Nikic is the return type also `array`, according to reflection? >> > > I'd prefer not to add either of them until the question of type > annotations on internal functions is solved more comprehensively in PHP 8. > In particular adding an "object" type will currently add additional cost to > the call. I hope that we'll solve this problem in PHP 8 and annotate > functions with types in a comprehensive way (including existing functions, > like get_object_vars). > > Nikita >
Any more feedback on the addition of get_mangled_object_vars()? Regarding the typehints, I've added an "array" return type for get_object_vars() in PHP 8 ( https://github.com/php/php-src/commit/252216b2ded7d3808e2a909bfea1e805ee17cde5) and will do the same for this function. The argument type is still blocked on some preparatory work. Nikita
  105844
June 6, 2019 08:05 ocramius@gmail.com (Marco Pivetta)
Provided feedback on the patch: looking good for me, not sure of this needs
an RFC or not.

On Thu, Jun 6, 2019, 09:53 Nikita Popov ppv@gmail.com> wrote:

> On Tue, May 14, 2019 at 4:45 PM Nikita Popov ppv@gmail.com> wrote: > >> On Tue, May 14, 2019 at 4:37 PM Marco Pivetta <ocramius@gmail.com> wrote: >> >>> >>> On Tue, May 14, 2019 at 4:29 PM Benjamin Morel morel@gmail.com> >>> wrote: >>> >>>> I like the explicitness of the proposal, but only if performance is as >>>> good >>>> as (array) cast. One of the reasons we use casting to array in >>>> libraries is >>>> not only to access all properties at once, but also because it's fast as >>>> it's implemented as an opcode and not a function call. Would this >>>> function >>>> come with its own opcode, like strlen() / gettype() / etc.? >>>> >>>> Ben >>>> >>> >>> Indeed. Besides that, this is a good chance to have an explicit `object` >>> parameter type. >>> >>> @Nikic is the return type also `array`, according to reflection? >>> >> >> I'd prefer not to add either of them until the question of type >> annotations on internal functions is solved more comprehensively in PHP 8. >> In particular adding an "object" type will currently add additional cost to >> the call. I hope that we'll solve this problem in PHP 8 and annotate >> functions with types in a comprehensive way (including existing functions, >> like get_object_vars). >> >> Nikita >> > > Any more feedback on the addition of get_mangled_object_vars()? > > Regarding the typehints, I've added an "array" return type for > get_object_vars() in PHP 8 ( > https://github.com/php/php-src/commit/252216b2ded7d3808e2a909bfea1e805ee17cde5) > and will do the same for this function. The argument type is still blocked > on some preparatory work. > > Nikita >
  105703
May 14, 2019 14:42 nikita.ppv@gmail.com (Nikita Popov)
On Tue, May 14, 2019 at 4:29 PM Benjamin Morel morel@gmail.com>
wrote:

> I like the explicitness of the proposal, but only if performance is as > good as (array) cast. One of the reasons we use casting to array in > libraries is not only to access all properties at once, but also because > it's fast as it's implemented as an opcode and not a function call. Would > this function come with its own opcode, like strlen() / gettype() / etc.? > > Ben >
I don't think an opcode is worthwhile in this case, because the primary cost is in constructing the property array. On this micro-benchmark https://gist.github.com/nikic/f592686c75d8d34d82ddc5900b598199 the results are: array cast: float(0.39156699180603) get_mangled_object_vars(): float(0.41520500183105) So no relevant difference in performance. Nikita