Hi Nikita,

While playing with typed properties, something that annoys me a lot, in the
context of a data mapper, is not to be able to use isset() to check whether
an object's property is initialized. The issue was already there with
properties that have been explicitly unset(), but will be exacerbated by
typed properties, which will be unset *by default*.

Sure, we have ReflectionProperty::isInitialized(), but reflection is slow
compared to direct property access, when reading a lot of objects.

For example, check these 3 ways of reading initialized public/protected
object properties by name, along with their timings for 100,000 iterations
(benchmark here
<https://gist.github.com/BenMorel/9a920538862e4df0d7041f8812f069e5#file-reflection-vs-array-cast-benchmark-php>
):

Using reflection: (890 ms, down to 384 ms using pre-instantiated
ReflectionProperty objects)

    $r = new \ReflectionClass($class);
>     foreach ($props as $prop) {
>         $p = $r->getProperty($prop);
>         $p->setAccessible(true);
>         if ($p->isInitialized($object)) {
>             $values[$p->getName()] = $p->getValue($object);
>         }
>     }


Using array cast: (193 ms)

    foreach ((array) $object as $key => $value) {
>         // Remove the "\0*\0" in front of protected properties
>         $pos = strrpos($key, "\0");
>         if ($pos !== false) {
>             $key = substr($key, $pos + 1);
>         }
>         $values[$key] = $value;
>     }


Using a bound closure and isset(): (145 ms)


>     (function() use ($props, & $values) {
>         foreach ($props as $prop) {
>             if (isset($this->{$prop})) { // skips NULL values as well :-(
>                 $values[$prop] = $this->{$prop};
>             }
>         }
>     })->bindTo($object, $object)();


Unfortunately, while the last approach is the fastest, and IMO the cleanest
one, it is currently unusable because there is no way to differentiate
between an uninitialized property and a NULL property.

Would it be possible to introduce another isset() operator, that would
return true for NULL values?
Note that this would also be useful when checking if an array key exists,
instead of having to switch from isset() to array_key_exists() when the
array may contain NULL values.

Ben

On Fri, 11 Jan 2019 at 17:38, Nikita Popov <nikita....@gmail.com> wrote:

> On Mon, Oct 22, 2018 at 1:58 PM Sebastian Bergmann <sebast...@php.net>
> wrote:
>
> > Am 26.09.2018 um 15:46 schrieb Nikita Popov:
> > > I'm pleased to announce that the typed properties RFC has been accepted
> > > with 70 votes in favor and one vote against. We will work to finalize
> and
> > > merge the implementation in the next few days.
> >
> > Any update on when this will be merged? Thanks!
> >
>
> Sorry for the long delay here. I've spent the last week fixing the
> remaining issues and cleaning up the patch, and...
>
> ...Typed properties are now merged into master! [1]
>
> It would be great if people could start experimenting with typed properties
> (e.g. by migrating over existing @var annotations and seeing what happens).
> The earlier we find issues in the implementation or semantics, the better.
>
> Thanks to everyone who worked on this RFC and participated in discussions.
> Special thanks to Bob Weinand who did most of the initial implementation
> work on this RFC.
>
> Regards,
> Nikita
>
> [1]:
>
> https://github.com/php/php-src/commit/e219ec144ef6682b71e135fd18654ee1bb4676b4
>

Reply via email to