<?php
class Book
{
protected $title;
protected $author;
protected $genres;
public function __construct()
{
$this->genres = new ArrayObject();
}
public function addGenre($genre)
{
$this->genres[] = $genre;
return $this;
}
public function getGenres()
{
return $this->genres;
}
public function setAuthor(Person $author)
{
$this->author = $author;
return $this;
}
public function getAuthor()
{
return $this->author;
}
public function setTitle($title)
{
$this->title = $title;
return $this;
}
public function getTitle()
{
return $this->title;
}
}
class Person
{
protected $firstName;
protected $lastName;
public function __construct($firstName = null, $lastName = null)
{
$this->setFirstName($firstName);
$this->setLastName($lastName);
}
public function setFirstName($firstName)
{
$this->firstName = $firstName;
return $this;
}
public function getFirstName()
{
return $this->firstName;
}
public function setLastName($lastName)
{
$this->lastName = $lastName;
return $this;
}
public function getLastName()
{
return $this->lastName;
}
}
interface Hydrator
{
public function hydrate($object, array $data);
public function extract($object);
}
class ReflectionHydrator implements Hydrator
{
public function hydrate($object, array $data)
{
$reflection = new ReflectionClass($object);
$transform = function ($key) {
return 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
};
foreach ($reflection->getMethod() as $method) {
if (!$method->isPublic() || 0 !== strpos($method->getName(), 'set')) {
continue;
}
$field = lcfirst(substr($method->getName(), 3));
// @todo
}
}
public function extract($object)
{
$data = array();
$reflection = new ReflectionClass($object);
$transform = function ($key) {
return '_' . strtolower(array_shift($key));
};
foreach ($reflection->getMethods() as $method) {
if (!$method->isPublic() || 0 !== strpos($method->getName(), 'get')) {
continue;
}
$field = lcfirst(substr($method->getName(), 3));
$normalized = preg_replace_callback('/([A-Z])/', $transform, $field);
$data[$normalized] = $method->invoke($object);
}
return $data;
}
}
class DryReflectionHydrator implements Hydrator
{
public function extract($object)
{
$transform = function ($key) {
return '_' . strtolower(array_shift($key));
};
$data = array();
// Process get methods
$this->processMethods('get', function ($field, ReflectionMethod $method) use (&$data, $transform) {
$normalized = preg_replace_callback('/([A-Z])/', $transform, $field);
$data[$normalized] = $method->invoke(null);
});
return $data;
}
public function hydrate($object, array $data)
{
$transform = function ($key) {
return 'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', $key)));
};
$this->processMethods('set', function($field, ReflectionMethod $method) use ($data, $transform) {
$method->invoke(null, $data[$transform($field)]);
});
}
protected function processMethods($prefix, $callback)
{
$reflection = new ReflectionClass($object);
foreach ($reflection->getMethods() as $method) {
if (!$method->isPublic() || 0 !== strpos($method->getName(), $prefix)) {
continue;
}
$field = lcfirst(substr($method->getName(), strlen($prefix)));
$callback($field, $method);
}
}
}
$book = new Book();
$book->setTitle('Harry potter');
$book->addGenre('Drama')->addGenre('Nosense');
$book->setAuthor(new Person('James', 'Bond'));
$hydrator = new ReflectionHydrator();
var_dump($hydrator->extract($book));
var_dump($hydrator->extract($book->getAuthor()));
$dryHydrator = new DryReflectionHydrator();
var_dump($dryHydrator->extract($book));
var_dump($dryHydrator->extract($book->getAuthor()));
- Output for 8.2.0 - 8.2.18, 8.3.0 - 8.3.6
- array(3) {
["genres"]=>
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(2) {
[0]=>
string(5) "Drama"
[1]=>
string(7) "Nosense"
}
}
["author"]=>
object(Person)#3 (2) {
["firstName":protected]=>
string(5) "James"
["lastName":protected]=>
string(4) "Bond"
}
["title"]=>
string(12) "Harry potter"
}
array(2) {
["first_name"]=>
string(5) "James"
["last_name"]=>
string(4) "Bond"
}
Warning: Undefined variable $object in /in/tTfdg on line 159
Deprecated: ReflectionClass::__construct(): Passing null to parameter #1 ($objectOrClass) of type object|string is deprecated in /in/tTfdg on line 159
Fatal error: Uncaught ReflectionException: Class "" does not exist in /in/tTfdg:159
Stack trace:
#0 /in/tTfdg(159): ReflectionClass->__construct('')
#1 /in/tTfdg(139): DryReflectionHydrator->processMethods('get', Object(Closure))
#2 /in/tTfdg(185): DryReflectionHydrator->extract(Object(Book))
#3 {main}
thrown in /in/tTfdg on line 159
Process exited with code 255. - Output for 8.1.0 - 8.1.28
- array(3) {
["genres"]=>
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(2) {
[0]=>
string(5) "Drama"
[1]=>
string(7) "Nosense"
}
}
["author"]=>
object(Person)#3 (2) {
["firstName":protected]=>
string(5) "James"
["lastName":protected]=>
string(4) "Bond"
}
["title"]=>
string(12) "Harry potter"
}
array(2) {
["first_name"]=>
string(5) "James"
["last_name"]=>
string(4) "Bond"
}
Warning: Undefined variable $object in /in/tTfdg on line 159
Deprecated: ReflectionClass::__construct(): Passing null to parameter #1 ($objectOrClass) of type object|string is deprecated in /in/tTfdg on line 159
Fatal error: Uncaught ReflectionException: Class "" does not exist in /in/tTfdg:159
Stack trace:
#0 /in/tTfdg(159): ReflectionClass->__construct('')
#1 /in/tTfdg(142): DryReflectionHydrator->processMethods('get', Object(Closure))
#2 /in/tTfdg(185): DryReflectionHydrator->extract(Object(Book))
#3 {main}
thrown in /in/tTfdg on line 159
Process exited with code 255. - Output for 8.0.0 - 8.0.30
- array(3) {
["genres"]=>
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(2) {
[0]=>
string(5) "Drama"
[1]=>
string(7) "Nosense"
}
}
["author"]=>
object(Person)#3 (2) {
["firstName":protected]=>
string(5) "James"
["lastName":protected]=>
string(4) "Bond"
}
["title"]=>
string(12) "Harry potter"
}
array(2) {
["first_name"]=>
string(5) "James"
["last_name"]=>
string(4) "Bond"
}
Warning: Undefined variable $object in /in/tTfdg on line 159
Fatal error: Uncaught ReflectionException: Class "" does not exist in /in/tTfdg:159
Stack trace:
#0 /in/tTfdg(159): ReflectionClass->__construct('')
#1 /in/tTfdg(142): DryReflectionHydrator->processMethods('get', Object(Closure))
#2 /in/tTfdg(185): DryReflectionHydrator->extract(Object(Book))
#3 {main}
thrown in /in/tTfdg on line 159
Process exited with code 255. - Output for 7.0.0 - 7.0.33, 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.31, 7.4.0 - 7.4.25, 7.4.27 - 7.4.33
- array(3) {
["genres"]=>
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(2) {
[0]=>
string(5) "Drama"
[1]=>
string(7) "Nosense"
}
}
["author"]=>
object(Person)#3 (2) {
["firstName":protected]=>
string(5) "James"
["lastName":protected]=>
string(4) "Bond"
}
["title"]=>
string(12) "Harry potter"
}
array(2) {
["first_name"]=>
string(5) "James"
["last_name"]=>
string(4) "Bond"
}
Notice: Undefined variable: object in /in/tTfdg on line 159
Fatal error: Uncaught ReflectionException: Class does not exist in /in/tTfdg:159
Stack trace:
#0 /in/tTfdg(159): ReflectionClass->__construct('')
#1 /in/tTfdg(142): DryReflectionHydrator->processMethods('get', Object(Closure))
#2 /in/tTfdg(185): DryReflectionHydrator->extract(Object(Book))
#3 {main}
thrown in /in/tTfdg on line 159
Process exited with code 255. - Output for 7.3.32 - 7.3.33, 7.4.26
- array(3) {
["genres"]=>
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(2) {
[0]=>
string(5) "Drama"
[1]=>
string(7) "Nosense"
}
}
["author"]=>
object(Person)#3 (2) {
["firstName":protected]=>
string(5) "James"
["lastName":protected]=>
string(4) "Bond"
}
["title"]=>
string(12) "Harry potter"
}
array(2) {
["first_name"]=>
string(5) "James"
["last_name"]=>
string(4) "Bond"
}
Fatal error: Uncaught ReflectionException: Class does not exist in /in/tTfdg:159
Stack trace:
#0 /in/tTfdg(159): ReflectionClass->__construct('')
#1 /in/tTfdg(142): DryReflectionHydrator->processMethods('get', Object(Closure))
#2 /in/tTfdg(185): DryReflectionHydrator->extract(Object(Book))
#3 {main}
thrown in /in/tTfdg on line 159
Process exited with code 255. - Output for 5.3.0 - 5.3.29, 5.4.0 - 5.4.45, 5.5.0 - 5.5.38, 5.6.0 - 5.6.40
- array(3) {
["genres"]=>
object(ArrayObject)#2 (1) {
["storage":"ArrayObject":private]=>
array(2) {
[0]=>
string(5) "Drama"
[1]=>
string(7) "Nosense"
}
}
["author"]=>
object(Person)#3 (2) {
["firstName":protected]=>
string(5) "James"
["lastName":protected]=>
string(4) "Bond"
}
["title"]=>
string(12) "Harry potter"
}
array(2) {
["first_name"]=>
string(5) "James"
["last_name"]=>
string(4) "Bond"
}
Notice: Undefined variable: object in /in/tTfdg on line 159
Fatal error: Uncaught exception 'ReflectionException' with message 'Class does not exist' in /in/tTfdg:159
Stack trace:
#0 /in/tTfdg(159): ReflectionClass->__construct('')
#1 /in/tTfdg(142): DryReflectionHydrator->processMethods('get', Object(Closure))
#2 /in/tTfdg(185): DryReflectionHydrator->extract(Object(Book))
#3 {main}
thrown in /in/tTfdg on line 159
Process exited with code 255.
preferences:
236.69 ms | 403 KiB | 407 Q