将可嵌入的教义声明为可为空或不为空



假设我有两个教义实体,PersonCompany。两者都有一个接受地址值对象的address字段。根据业务规则,Company::Address是必需的,而Person::Address可以为 null。

原则 2.5 提出了可嵌入类型,它显然是在考虑价值对象的情况下构建的,事实上,我认为它是我的情况的完美解决方案。

但是,有一件事我不能做:声明Person::Address可为空,而Company::Address则不为空。嵌入的字段本身存在布尔nullable属性,但这当然适用于嵌入地址的每个实体。

有谁知道我是否遗漏了什么,或者这是否是由于技术限制,是否有解决方法等?现在,我看到的唯一解决方案是将所有可嵌入字段声明为nullable: true并在代码中处理约束。

有谁知道我是否错过了什么

原则 2 不支持可为空的可嵌入对象。预计他们将进入版本 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
        );
    }
}

(哈里森·布朗的片段(

getter 内部逻辑的问题是您无法直接访问属性(如果您这样做,您将错过此特定行为(......

我试图使用自定义水化器来解决这个问题,但问题是学说不允许在调用 find((、findOneBy((...以及不使用查询生成器的方法。

这是我的解决方案:

  1. 想象一下,我们有一个看起来像这样的实体:
<?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;
        }
    }
}

然后,您需要创建一个事件侦听器,以便在 postLoad 事件中初始化此实体:

<?php
use DoctrineORMEventLifecycleEventArgs;
class InitialiseDoctrineEntity
{
    public function postLoad(LifecycleEventArgs $eventArgs): void
    {
        $entity = $eventArgs->getEntity();
        if ($entity instanceof CanBeInitialized) {
            $entity->initialize();
        }
    }
}

这种方法的优点在于我们可以使实体适应我们的需求(不仅仅是拥有可为空的可嵌入对象(。例如:在领域驱动设计中,当我们使用六边形架构作为战术方法时,我们可以初始化学说实体,并根据需要进行所有更改,以使我们的领域实体。

相关内容

  • 没有找到相关文章

最新更新