zubzizub
1/8/2018 - 10:11 AM

рефлексия и class Hydrator

Использование рефлексии в 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];
    }
}