我有主实体
/**
* @ORMEntity()
*/
class Document
{
/**
* @var int
* @ORMId()
* @ORMColumn(type="integer")
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var DocumentStatus
* @ORMManyToOne(targetEntity="DocumentStatus")
*/
private $status;
/**
* @var string
* @ORMColumn(type="text")
*/
private $text;
}
和查找"枚举"实体(在应用程序部署时播种)
/**
* @ORMEntity(repositoryClass="DocumentStatusRepository");
*/
class DocumentStatus
{
const DRAFT = 'draft';
const PENDING = 'pending';
const APPROVED = 'approved';
const DECLINED = 'declined';
/**
* @var int Surrogate primary key
* @ORMId()
* @ORMColumn(type="integer")
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string Natural primary key (name for developers)
* @ORMColumn(type="string", unique=true)
*/
private $key;
/**
* @var string Short name for users
* @ORMColumn(type="string", unique=true)
*/
private $name;
/**
* @var string Full decription for users
* @ORMColumn(type="string", nullable=true, unique=true)
*/
private $description;
}
使用简单的存储库
class DocumentStatusRepository extends EntityRepository
{
public function findOneByKey($key)
{
return parent::findOneBy(['key' => $key]);
}
}
我想通过引入等方法来封装文档生命周期的领域逻辑
public function __construct($text)
{
$this->text = $text;
$this->status = $something->getByKey(DocumentStatus::DRAFT);
}
public function approve()
{
try {
$this->doSomeDomainActions();
$this->status = $something->getByKey(DocumentSatus::DRAFT);
} catch (SomeDomainException($e)) {
throw new DocumentApproveException($e);
}
}
...
或
public function __construct($text)
{
$this->text = $text;
$this->status = $something->getDraftDocumentStatus()
}
public function approve()
{
$this->status = $something->getApprovedDocumentStatus()
}
...
没有公共设置者。此外,我希望保持文档的松散耦合和可测试性。
我看到了下一条路:
- 通过实体创建时的构造函数和postLoad subscriber中的公共setter,将DocumentStatuspository(或封装它的服务)永久注入到每个实例中
- 在应用程序引导程序或loadClassMetadata上通过静态Document方法永久注入DocumentStatusRegosity
- 在构造函数和Document::approve等方法中临时注入DocumentStatusRegository
- 将setStatus()方法与基于$status->键值的复杂逻辑一起使用
- 在某些DocumentManager中封装文档域逻辑,并使用类似于简单数据存储或DTO的文档实体:(
还有其他方法吗?从长远来看,哪种方法更容易、更方便使用?
-
使用生成的文档标识
现在您可以在数据库的一侧生成标识。所以你save
文档从域的角度处于不一致的状态。实体/聚合should be identified
,如果它没有id,则不应该存在
如果您真的想保留数据库序列,请将方法添加到存储库中,该存储库将为您生成id
更好的方法是使用uuid生成器,例如ramsey/uuid。并且CCD_ 3是id CCD_。 -
DocumentStatus
作为值对象
为什么文档状态为实体?它看起来确实像一个简单的Value对象。然后可以使用可嵌入注释。所以它将留在数据库中的同一个表中,不需要进行内部联接
DocumentStatus获取行为,例如->draftDocumentStatus(),它returns NEW DocumentStatus
具有草稿状态,因此您可以将旧实例切换为新实例。ORM会做剩下的。 -
DocumentStatusReserve
如果您真的想保留DocumentStatus作为实体,在我看来is wrong
您不应该有DocumentStatusRepository
Document是您的聚合根,而DocumentStatus的only entrance
应该是通过聚合根
因此,您将只有DocumentRepository,它将负责整个聚合的rebuilding
和saving
。此外,您还应该更改映射
它应该具有FETCH=EAGER
类型,因此它将与Document一起检索DocumentStatus
其次,您应该使用CASCADE=ALL
和ORPHANREMOVAL=TRUE
进行映射
否则,如果是remove
文档,则为DocumentStatuswill stay in the database
。