Использование рефлексии в php (отсюда http://www.elisdn.ru/blog/106/domain-native-repository) и класс Hydrator для заполнения объекта данными, полученными, например из бд.
<?php
$reflection = new \ReflectionClass(Employee::class);
$property = $reflection->getProperty('id');
$property->setAccessible(true);
$property->setValue($employee, new EmployeeId(25));
namespace app\repositories;
class Hydrator
{
public function hydrate($class, array $data)
{
$reflection = new \ReflectionClass($class);
$target = $reflection->newInstanceWithoutConstructor();
foreach ($data as $name => $value) {
$property = $reflection->getProperty($name);
$property->setAccessible(true);
$property->setValue($target, $value);
}
return $target;
}
}
// оптимизированный класс Hydrator, если планируется создание множество объектов
// т.к. new \ReflectionClass($class) замедляет работу
class Hydrator
{
private $reflectionClassMap;
public function hydrate($class, array $data)
{
$reflection = $this->getReflectionClass($class);
$target = $reflection->newInstanceWithoutConstructor();
foreach ($data as $name => $value) {
$property = $reflection->getProperty($name);
if ($property->isPrivate() || $property->isProtected()) {
$property->setAccessible(true);
}
$property->setValue($target, $value);
}
return $target;
}
private function getReflectionClass($className)
{
if (!isset($this->reflectionClassMap[$className])) {
$this->reflectionClassMap[$className] = new \ReflectionClass($className);
}
return $this->reflectionClassMap[$className];
}
}