Php Doctrine2:实体和单表继承映射的有界上下文。我有点困惑,我做得对吗
长话短说 我使用Doctrine的单表继承映射来映射一个公共实体的三个不同上下文(类):NotActivatedCustomer、DeletedCustomer和Customer。此外,还有一个AbstractCustomer,其中包含以下内容:Php Doctrine2:实体和单表继承映射的有界上下文。我有点困惑,我做得对吗,php,doctrine,domain-driven-design,bounded-contexts,Php,Doctrine,Domain Driven Design,Bounded Contexts,长话短说 我使用Doctrine的单表继承映射来映射一个公共实体的三个不同上下文(类):NotActivatedCustomer、DeletedCustomer和Customer。此外,还有一个AbstractCustomer,其中包含以下内容: App\Identity\Domain\Customer\AbstractCustomer: 类型:实体 inheritanceType:单表 鉴别器列: 姓名:discr 类型:字符串 歧视地图: 客户:App\Identity\Domain\Cus
App\Identity\Domain\Customer\AbstractCustomer:
类型:实体
inheritanceType:单表
鉴别器列:
姓名:discr
类型:字符串
歧视地图:
客户:App\Identity\Domain\Customer\Customer
NotActivatedCustomer:App\Identity\Domain\Customer\NotActivatedCustomer
DeletedCustomer:App\Identity\Domain\Customer\DeletedCustomer
表:客户
身份证件:
身份证件:
类型:客户识别码
独一无二:真的
发电机:
策略:定制
自定义IDGenerator:
类别:Symfony\Bridge\Doctrine\IdGenerator\UuidV4Generator
领域:
电邮:
类型:电子邮件
长度:180
独一无二:真的
子类型定义示例:
我认为你想避免客户变成上帝的对象是绝对正确的。继承是一种方法,但对处于不同状态的客户使用它可能会导致问题
在我的经历中,有两个关键问题:
随着新状态的出现,您会继续添加不同的继承实体吗
当客户处于两种不同的状态时会发生什么情况,例如,一个客户是未激活的客户
,但现在是删除的客户
因此,我只在继承的类型真正是更特定的类型时才保留继承,其中给定的实体在其整个生命周期中将仅是这些类型中的一种。例如,汽车不会变成摩托车
我有两种不同的模式来解决这个问题。我倾向于从第一个开始,然后转到第二个
interface DeletedCustomer
{
public function getDeletedAt(): DateTime;
}
interface NotActivatedCustomer
{
public function getCreatedAt(): DateTime;
}
class Customer implements DeletedCustomer, NotActivatedCustomer
{
private $id;
private $name;
private DateTime $deletedAt;
private bool $isActivated = false;
public function getDeletedAt(): DateTime {...}
public function getCreatedAt(): DateTime {...}
}
class DeletedCustomerRepository
{
public function findAll(): array
{
return $this->createQuery(<<<DQL
SELECT customer
FROM Customer
WHERE customer.deletedAt IS NOT NULL
>>>)->getQuery()->getResults();
}
}
class NotActivatedCustomerRepository
{
public function findAll(): array
{
return $this->createQuery(<<<DQL
SELECT customer
FROM Customer
WHERE customer.isActivated = false
>>>)->getQuery()->getResults();
}
}
class DeletedCustomerService
{
public function doTheThing(DeletedCustomer $customer) {}
}
接口删除客户
{
公共函数getDeletedAt():DateTime;
}
接口NotActivatedCustomer
{
公共函数getCreatedAt():DateTime;
}
类Customer实现DeletedCustomer,而不是ActivatedCustomer
{
私人$id;
私人$name;
私有日期时间$deletedAt;
私有bool$isActivated=false;
公共函数getDeletedAt():日期时间{…}
公共函数getCreatedAt():日期时间{…}
}
类DeletedCustomerRepository
{
公共函数findAll():数组
{
返回$this->createQuery()->getQuery()->getResults();
}
}
类NotActivatedCustomerRepository
{
公共函数findAll():数组
{
返回$this->createQuery()->getQuery()->getResults();
}
}
类DeletedCustomerService
{
公共函数doTheThing(DeletedCustomer$customer){}
}
这减少了耦合,这是上帝对象的主要问题之一。因此,当这些列开始大量增加时,我可以将它们转移到加入客户
的真实实体。引用DeletedCustomer
的组件仍将收到一个
第二种模式是事件源lite—与“CustomerLifeCycleeEvent”实体具有多对一关系。根据客户是否有“已删除”事件进行查询。第二种方法要复杂得多,包括更新和查询。您仍然可以拥有返回实体的专用存储库,如DeletedCustomer
,但您需要做更多的样板