zf2 - Вложенные агрегатные гидраторы

Можно ли вкладывать агрегатные гидраторы? Если у меня есть следующие классы:

class Appointment{
    public date;
    public startTime;
    public endTime;
    public User; //* @var User */
}

class User{
    public Location; //* @var Location*/ 
}

... заполняется следующим AggregateHydrator (созданным на фабрике):

class AppointmentModelHydratorFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $serviceLocator) {
        $serviceManager = $serviceLocator->getServiceLocator();
        $arrayHydrator = new ArraySerializable();
        $arrayHydrator->addStrategy('date', new DateTimeStrategy())
            ->addStrategy('endTime', new TimeStrategy())
            ->addStrategy('startTime', new TimeStrategy());

        $aggregateHydrator = new AggregateHydrator();
        $aggregateHydrator->add($arrayHydrator);
        $aggregateHydrator->add($serviceLocator->get('Hydrator\User'));
        return $aggregateHydrator;
    }
}

С UserHydratorFactory выглядит как:

class UserHydratorFactory implements FactoryInterface
{
     public function createService(ServiceLocatorInterface $serviceLocator) {
        $sm = $serviceLocator->getServiceLocator();
        $userHydrator = new UserHydrator($sm->get('User\Mapper'));
        $aggregateHydrator = new AggregateHydrator();
        $aggregateHydrator->add($userHydrator );
        $aggregateHydrator->add($sm->get('HydratorManager')->get('Hydrator\User\Location'));
        return $aggregateHydrator;
}

}

Это исключение, так как модель возвращается как нулевая, но если я закомментирую добавление гидратора местоположения в гидратор пользователя, он будет работать нормально (хотя и без загруженных данных о местоположении). Так что мне было интересно, если совокупные гидраторы могут быть вложены?

1 ответ

Это не встроенный, но выполнимый.

namespace Hydrator;
use Zend\Stdlib\Hydrator\HydratorInterface;
class NestedHydrator implements HydratorInterface
{
    protected $inner_hydrator;
    private $empty;


    public function __construct ($inner_hydrator, $empty)
    {
        $this->inner_hydrator = $inner_hydrator;
        $this->empty = $empty;
    }


    public function extract ($object)
    {
        return [
            $this->getPath() => $this->inner_hydrator->extract ($object->{$this->getPath()})
        ];
    }


    public function hydrate (array $data, $object)
    {
        $object->{$this->getPath()} = $this->inner_hydrator->hydrate ($data [$this->getPath()], $this->empty);

        return $object;
    }


    protected function getPath ()
    {
        return get_class ($this->empty);
    }
}

А потом:

$u = new User();
$u->Location = "4 Clinton Rd.";

$a = new Appointment();
$a->date = "yesterday";
$a->startTime = "7:00";
$a->endTime = "8:00";
$a->User = $u;

$h = new AggregateHydrator();
$h->add (new ObjectProperty());
$nested = new \Hydrator\NestedHydrator(new ObjectProperty(), new User());
$h->add ($nested);
$data = $h->extract ($a);

$b = $h->hydrate ($data, new Appointment());
$this->assertEquals ($a, $b);
Другие вопросы по тегам