3v4l.org

run code in 300+ PHP versions simultaneously
<?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'); $hydrator = new ReflectionHydrator(); var_dump($hydrator->extract($book));
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, 7.0.0 - 7.0.33, 7.1.0 - 7.1.33, 7.2.0 - 7.2.33, 7.3.0 - 7.3.33, 7.4.0 - 7.4.33, 8.0.0 - 8.0.30, 8.1.0 - 8.1.27, 8.2.0 - 8.2.17, 8.3.0 - 8.3.4
array(3) { ["genres"]=> object(ArrayObject)#2 (1) { ["storage":"ArrayObject":private]=> array(2) { [0]=> string(5) "Drama" [1]=> string(7) "Nosense" } } ["author"]=> NULL ["title"]=> string(12) "Harry potter" }

preferences:
290.74 ms | 405 KiB | 403 Q