Skip to content

Instantly share code, notes, and snippets.

@Ocramius Ocramius/Foo.php

Last active Mar 22, 2020
Embed
What would you like to do?
Self hydrating object proxy in PHP Provides faster hydration by removing the need for reflection.

This piece of code tries to reduce the performance overhead needed to populate an object's properties via reflection.

An example of its usage can be found at http://3v4l.org/he2dF

<?php
class Foo
{
protected $foo;
protected $bar;
protected $baz;
}
<?php
class FooSelfHydratingProxy extends Foo implements HydratorInterface
{
/** zero-argument constructor since this is just a helper class for hydration */
public function __construct()
{
}
/**
* the `Foo` typehint is not part of the interface - here only for the sake of readability/clearness
*/
public function hydrate($data, Foo $object)
{
$object->foo = $data['foo'];
$object->bar = $data['bar'];
$object->baz = $data['baz'];
}
/**
* the `Foo` typehint is not part of the interface - here only for the sake of readability/clearness
*/
public function extract(Foo $object)
{
return array('foo' => $object->foo, 'bar' => $object->bar, 'baz' => $object->baz);
}
}
<?php
$iterations = 100000;
class A {protected $a; protected $b; protected $c;}
class AHydrator extends A {
public function hydrate(A $a, array $data)
{
$a->a = $data['a'];
$a->b = $data['b'];
$a->c = $data['c'];
}
}
$data = array('a' => 1, 'b' => 2, 'c' => 3);
$a = new A();
$h = new AHydrator();
for ($i = 0; $i < $iterations; $i++) {
$h->hydrate($a, $data);
}
<?php
$iterations = 100000;
class A {protected $a; protected $b; protected $c;}
$rA = new ReflectionProperty('A', 'a');
$rB = new ReflectionProperty('A', 'b');
$rC = new ReflectionProperty('A', 'c');
$rA->setAccessible(true);
$rB->setAccessible(true);
$rC->setAccessible(true);
$data = array('a' => 1, 'b' => 2, 'c' => 3);
$a = new A();
for ($i = 0; $i < $iterations; $i++) {
$rA->setValue($a, $data['a']);
$rB->setValue($a, $data['b']);
$rC->setValue($a, $data['c']);
}
@prograhammer

This comment has been minimized.

Copy link

prograhammer commented Jul 31, 2015

This is brilliant @Ocramius! I was looking for a way to hydrate my entities without using slow Reflection or adding setters unnecessarily.

@Ocramius

This comment has been minimized.

Copy link
Owner Author

Ocramius commented Aug 1, 2015

@prograhammer this is just meant for D2 internals, not for the "general public"

@aderuwe

This comment has been minimized.

Copy link

aderuwe commented Aug 25, 2015

@Ocramius it's a valid strategy perhaps though, for projects that can't use the D2 ORM ...

@ChubV

This comment has been minimized.

Copy link

ChubV commented Jan 13, 2016

@Ocramius so if this change will happen in D2 all entities should be refactored to have protected properties instead of private? Also extending entity can have some drawbacks... Please, look at this example . It also has nice performance and can be used to set private properties.

@flowl

This comment has been minimized.

Copy link

flowl commented Feb 18, 2020

Why does HydratorA extend A? It's confusing without doing anything. Also the questino is not answered: Why was the reflection there in the first place? Probably because of unknown properties..

@Ocramius

This comment has been minimized.

Copy link
Owner Author

Ocramius commented Feb 18, 2020

@flowl that's an old concept that I used in a library called GeneratedHydrator: https://github.com/Ocramius/GeneratedHydrator

The idea is that by using inheritance, you can avoid property access hooks that are used by PHP to determine whether you can access a field or not.

@flowl

This comment has been minimized.

Copy link

flowl commented Feb 18, 2020

The idea is that by using inheritance, you can avoid property access hooks that are used by PHP to determine whether you can access a field or not.

Ahh you are right, I remember... extending a class gives the current one permission to access non-public properties.
I just downloaded GeneratedHydrator to try it out :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.