在条令实体内设置/更新关联查找字段的最佳方式是什么



我有主实体

/**
* @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的文档实体:(

还有其他方法吗?从长远来看,哪种方法更容易、更方便使用?

  1. 使用生成的文档标识
    现在您可以在数据库的一侧生成标识。所以你save文档从域的角度处于不一致的状态。实体/聚合should be identified,如果它没有id,则不应该存在
    如果您真的想保留数据库序列,请将方法添加到存储库中,该存储库将为您生成id
    更好的方法是使用uuid生成器,例如ramsey/uuid。并且CCD_ 3是id CCD_。

  2. DocumentStatus作为值对象
    为什么文档状态为实体?它看起来确实像一个简单的Value对象。然后可以使用可嵌入注释。所以它将留在数据库中的同一个表中,不需要进行内部联接
    DocumentStatus获取行为,例如->draftDocumentStatus(),它returns NEW DocumentStatus具有草稿状态,因此您可以将旧实例切换为新实例。ORM会做剩下的。

  3. DocumentStatusReserve
    如果您真的想保留DocumentStatus作为实体,在我看来is wrong您不应该有DocumentStatusRepository
    Document是您的聚合根,而DocumentStatus的only entrance应该是通过聚合根
    因此,您将只有DocumentRepository,它将负责整个聚合的rebuildingsaving。此外,您还应该更改映射
    它应该具有FETCH=EAGER类型,因此它将与Document一起检索DocumentStatus
    其次,您应该使用CASCADE=ALLORPHANREMOVAL=TRUE进行映射
    否则,如果是remove文档,则为DocumentStatuswill stay in the database

最新更新