mar*_*rcv 7 php orm doctrine value-objects doctrine-orm
假设我有两个Doctrine实体,Person并且Company.两者都有一个address接受地址值对象的字段.根据业务规则,Company::Address必需时Person::Address可以为null.
Doctrine 2.5提出了Embeddable类型,它显然是以值对象为基础构建的,实际上,我认为它是我案例的完美解决方案.
但是,有一件事我不能做:声明可以Person::Address为空而Company::Address不是.nullableEmbeddable的字段本身存在布尔属性,但当然这适用于嵌入地址的每个实体.
有人知道我是否遗漏了某些东西,或者这是否是由于技术限制,是否有解决方法等?现在,我看到的唯一解决方案是将所有Embeddable字段声明为nullable: true并在我的代码中处理约束.
有人知道我是否遗漏了什么
Doctrine 2不支持Nullable embeddables.预计它们将用于版本3.
如果有解决方法
解决方案是"不要在那里使用嵌入式,并[[]]用嵌入式替换字段[手动]"(@Ocramius)
例:
class Product
{
private $sale_price_amount;
private $sale_price_currency;
public function getSalePrice(): SalePrice
{
if (is_null($this->sale_price_currency)
|| is_null($this->sale_price_amount)
) {
return null;
}
return new SalePrice(
$this->sale_price_currency,
$this->sale_price_amount
);
}
}
Run Code Online (Sandbox Code Playgroud)
(Harrison Brown的片段)
getter 内部逻辑的问题是你无法直接访问属性(如果你这样做,你就会错过这个特定的行为)...
我试图使用自定义水化器来解决这个问题,但问题是,学说不允许在调用 find()、findOneBy()...以及不使用 queryBuilder 的方法时使用自定义水化器。
这是我的解决方案:
<?php
interface CanBeInitialized
{
public function initialize(): void;
}
class Address
{
private $name;
public function name(): string
{
return $this->name;
}
}
class User implements CanBeInitialized
{
private $address;
public function address(): ?Address
{
return $this->address;
}
public function initialize(): void
{
$this->initializeAddress();
}
private function initializeAddress(): void
{
$addressNameProperty = (new \ReflectionClass($this->address))->getProperty('value');
$addressNameProperty->setAccessible(true);
$addressName = $addressNameProperty->getValue($this->address);
if ($addressName === null) {
$this->address = null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您需要创建一个 EventListener 以便在 postLoad 事件中初始化该实体:
<?php
use Doctrine\ORM\Event\LifecycleEventArgs;
class InitialiseDoctrineEntity
{
public function postLoad(LifecycleEventArgs $eventArgs): void
{
$entity = $eventArgs->getEntity();
if ($entity instanceof CanBeInitialized) {
$entity->initialize();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这种方法的优点在于我们可以根据我们的需求调整实体(不仅仅是具有可为空的嵌入项)。例如:在领域驱动设计中,当我们使用六角形架构作为战术方法时,我们可以使用我们想要的领域实体所需的所有更改来初始化 Doctrine 实体。
| 归档时间: |
|
| 查看次数: |
2211 次 |
| 最近记录: |