Skip to content

Instantly share code, notes, and snippets.

@Ocramius
Last active March 12, 2021 14:14
Show Gist options
  • Save Ocramius/5365052 to your computer and use it in GitHub Desktop.
Save Ocramius/5365052 to your computer and use it in GitHub Desktop.
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']);
}
@flowl
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
Copy link
Author

@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
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