【问题标题】:DDD Value Objects and Entity Without ORM Mapping in PHPPHP中没有ORM映射的DDD值对象和实体
【发布时间】:2020-06-17 21:01:20
【问题描述】:

首先,据我所知,DDD 中的实体与值对象几乎相同,只是实体具有标识。我读过的每一篇文章都说实体 id 与任何 ORM 工具都有 ORM 映射。但我不想在 Entity 中使用 ORM 映射。相反,我想在没有映射的情况下使用存储库接口进行数据库操作。而且,在这种情况下,我不知道该怎么做。

我会用下面的例子在脑海中解释

假设我有一个 TODO 应用程序,TODO 中有一些问题,每个问题都有一些答案。

我们有 3 个值对象(或实体): 去做 待办事项 TodoQuestionValue

现在,我认为我有一个 TODO 的值对象(或实体)。这个值对象有一个方法来获取获取 TodoQuestion 值对象数组的问题。在 TodoQuestion 值对象内部,我们有一个方法来获取获取 TodoQuestionValue 数组的问题值。

<?php
class Todo{
   private int $id;
   /**
    * @param array<TodoQuestion> $questions
    */
   private array $questions;
   private TodoRepositoryInterface $repository;
   public function __constructor(TodoRepositoryInterface $repository){
      $this->repository = $repository;
   }
   public function getQuestions(){
      $this->questions = $this->repository->listQuestionsByTodoId($this->id);
   }
}
<?php
class TodoQuestion{
   private int $id;
   private string $question;
   /**
    * @param array<TodoQuestionValue> $values
    */
   private array $values;
   private TodoRepositoryInterface $repository;
   public function __constructor(TodoRepositoryInterface $repository){
      $this->repository = $repository;
   }
   public function getValues(){
      $this->values = $this->repository->listValuesByQuestionId($this->id);
   }
}

现在,我想听听您对我如何通过遵循 DDD 规则来塑造这个结构的意见。

谢谢。

【问题讨论】:

    标签: php orm entity domain-driven-design value-objects


    【解决方案1】:

    假设我有一个 TODO 应用程序,TODO 中有一些问题,每个问题都有一些答案。

    您只需将其转换为代码即可。这里唯一的实体是 Todo。使其成为聚合根并为其创建存储库。

    <?php
    
    class Todo
    {
        private int $id;
        /**
         * @param array<TodoQuestion> $questions
         */
        private array $questions;
    
        public function getQuestions()
        {
            return $this->questions;
        }
    }
    

    问题有答案。您可以使用 2 个值对象对其进行建模:问题和答案。

    <?php
    
    class TodoQuestion
    {
        private string $question;
        private array $values;
        /**
         * @var TodoAnswer[]
         */
        private array $answers;
    
        public function getValues()
        {
            return $this->values;
        }
    
        public function getAnswers(): array
        {
            return $this->answers;
        }
    }
    

    您的模型不应依赖于存储库。存储库任务是保存聚合的状态并在查询聚合时重建相同的状态。

    interface TodoRepository {
        public function save(Todo $todo): void;
    
        public function todoOfId(TodoId $id): Todo;
    }
    

    您不需要超过这两种方法。如果您想获得一个 Todo 的问题列表,您只需获取 Todo 聚合根,然后调用-&gt;getQuestions()。在您的存储库实现中,您可以决定使用 orm、编写原始查询、序列化聚合然后保存它......只要确保您的模型与这些基础架构问题解耦,可能性是无穷无尽的。

    【讨论】:

    • 非常感谢您的努力和回答。为了澄清,我想问一些事情。我认为没有愚蠢的问题原则也适用于这里 :) 我从哪里调用 TodoRepository?通常我有存储库被注入的“服务类”。这些存储库返回原始值而不是值对象。我还应该将待办事项存储库包装在那里吗?在这种情况下,初始化 todoQuestion 的最佳方法是什么?应该在聚合根中完成吗?维伦丹克
    • 存储库应该只返回一个聚合根或聚合根的集合。您可以从域服务或应用程序服务调用存储库。要向 Todo 添加问题,您首先获取存储库中的 Todo 对象,创建一个新的问题对象并将其添加到 $todo->addquestion($question)。然后您可以使用存储库保存聚合
    猜你喜欢
    • 2010-10-31
    • 2017-02-11
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 2021-10-31
    • 2010-10-04
    • 2017-10-13
    • 1970-01-01
    相关资源
    最近更新 更多