3v4l.org

run code in 150+ php & hhvm versions
Bugs & Features
<?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 7.0.0 - 7.1.0
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 5.3.0 - 5.6.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" } 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.