我之前使用服务层构建了复杂的模型(一个包含许多其他类型模型的对象),其中不同的映射器作为构造函数传入。
例如。
class UserService{
public function __construct(UserMapper $userMapper, AddressMapper $addressMapper, AppointmentsMapper $appointmentsMapper){}
public function loadById($id) : User {
$user = $this->userMapper->find($id);
$appointments = $this->appointmentsMapper->findByUser($user);
$user->setAppointments($appointments);
$address = $this->addressMapper->findByUser($user);
$user->setAddress($address);
//..etc..
}
}
上面是一个简化的例子。在我的领域中,我使用工厂中使用的多种服务来创建复杂的对象图。
在阅读了MaltBlue上关于聚合水合器的非常有趣的文章后,我尝试采用这种方法来简化对象创建过程。我喜欢创建一个 HydratingResulset 并将 RowObjectPrototype 设置为要返回的对象的想法。
我想我需要一些关于如何在现实世界中进行这项工作的指示。例如,当使用 AggregateHydrator 时,我可以根据传递给 hydrator 的用户 ID 加载用户约会历史记录。
class UserModelHydratorFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$serviceManager = $serviceLocator->getServiceLocator();
/**
* Core hydration
*/
$arrayHydrator = new ArraySerializable();
$arrayHydrator->addStrategy('dateRegistered', new DateTimeStrategy());
$aggregateHydrator = new AggregateHydrator();
$aggregateHydrator->add($arrayHydrator);
$aggregateHydrator->add($serviceLocator->get('Hydrator\Address'));
$aggregateHydrator->add($serviceLocator->get('Hydrator\Appointments'));
return $aggregateHydrator;
}
}
...例如,用户地址水合器看起来像这样:
class UserAddressHydrator implements HydratorInterface{
protected $locationMapper;
public function __construct(LocationMapper $locationMapper){
$this->locationMapper = $locationMapper;
}
public function hydrate(array $data, $object){
if(!$object instanceof User){
return;
}
if(array_key_exists('userId', $data)){
$object->setAddress($this->locationMapper->findByClientId($data['userId']));
}
return $object;
}
}
这完美地工作。尽管使用了 AggregateHydrator 方法,但这意味着每个具有 Address 作为属性的对象都意味着它需要自己的 hydrator。因此,如果我正在构建一个也有地址的公司模型,则需要另一个(几乎相同的)水合器,因为上面的水合器是硬编码的以填充用户模型(并期望包含 userId 键的数据)。这意味着对于每个关系/交互(has-a)都需要它自己的 hydrator 来生成它。这正常吗?所以我需要一个 UserAddressHydrator、CompanyAddressHydrator、SupplierAddressHydrator、AppointmentAddressHydrator - 都与上述代码几乎相同,只是填充不同的对象?
拥有一个 AddressHydrator 会更简洁,它接受一个 addressId 并返回 Address 模型。这导致我查看 hydrator 策略,这似乎是完美的,尽管它们仅适用于单个值,因此无法查看传入数组以查看是否存在 pk/fk / 识别键并基于该值加载.
我很感激对这种方法的一些澄清,感觉就像我一路迷路了。