Php 在DDD中,您将公共数据设置器放在哪里进行更新/插入?

Php 在DDD中,您将公共数据设置器放在哪里进行更新/插入?,php,service,repository,domain-driven-design,Php,Service,Repository,Domain Driven Design,我有一个关于领域驱动设计的问题。让我们想象一个简单的场景 我有一个名为“User”的实体,它有一些属性。其中一个属性是“创建日期”、“修改日期”和“上次登录ip” 假设我们有一个表单,它创建了一个用户,如果创建成功,它将对用户进行身份验证 控制器获取POST数据 通过方法“createAndAuthenticateUser”将post数据发送到UsersService 服务接收数据并对其进行验证(在此处执行,而不是在实体中执行,因为验证与存储库绑定,例如验证电子邮件是否已存在等) 如果验证正常,

我有一个关于领域驱动设计的问题。让我们想象一个简单的场景

我有一个名为“User”的实体,它有一些属性。其中一个属性是“创建日期”、“修改日期”和“上次登录ip”

假设我们有一个表单,它创建了一个用户,如果创建成功,它将对用户进行身份验证

  • 控制器获取POST数据
  • 通过方法“createAndAuthenticateUser”将post数据发送到UsersService
  • 服务接收数据并对其进行验证(在此处执行,而不是在实体中执行,因为验证与存储库绑定,例如验证电子邮件是否已存在等)
  • 如果验证正常,它将创建一个新实体,将数据分配给该实体,然后将该实体发送到存储库进行保存。然后,存储库将该用户保存在数据源中
  • 到目前为止还不错。这里的问题是,必须在此服务方法中设置创建/修改/上次登录的日期

    如果我想在更新用户对象时随时设置修改的日期(例如,在登录时我想更新修改的日期,在用户更新时我想再次修改,在用户创建时我想再次修改),该怎么办

    从逻辑上讲,我自己的答案是将其放入存储库中,如

    (这里有点像元代码,语法不重要)

    然而,从我所阅读的内容来看,存储库应该总是在调用方和数据源之间映射数据(反之亦然),就这样,它不应该设置数据或类似的东西

    当然,你可以告诉我这是一个行为,所以我可以有一个行为,上面写着$User->markAsUpdated()这将只设置date_modified属性。但同样,这意味着必须从多个位置调用此方法,而不是从一个集中的位置进行调用。我看不到在存储库中没有此代码的好处


    有什么想法吗?

    如果出于某种原因,上次登录ip的概念实际上是用户的核心,那么在登录时更新用户是有效的。事实上,您对执行更新以保存上次登录ip表示担忧,这意味着它实际上不是一个用户概念,而是一个安全、审计或用户概念之外的概念。


    至于设置修改和创建日期,我会提出相同的论点。如果系统要求用户同时维护和公开这些信息,那么在用户上创建一个私有方法,每个公共方法在修改状态时调用该方法,这将设置修改日期。如果不是,那么您几乎有两个选择ns-创建一个审计服务,该服务将收到更新通知并保留自己的审计记录,或者让存储库在更新记录时设置字段。

    如果由于某种原因,最后登录ip的概念实际上是用户的核心,那么在登录时更新用户是有效的执行更新以保存最后一个登录IP意味着它实际上不是一个用户概念,而是一个安全、审计或用户概念之外的概念


    至于设置修改和创建日期,我会提出相同的论点。如果系统要求用户同时维护和公开这些信息,那么在用户上创建一个私有方法,每个公共方法在修改状态时调用该方法,这将设置修改日期。如果不是,那么您几乎有两个选择NS -创建一个被通知更新的审计服务,并保存自己的审计记录,或者在更新记录时存储库设置。< / P>这不解决您的主要问题,但是如果您正在使用MySQL,则考虑使用“on更新CurrnTyTimeType”。在db级别,其他rdbms可能有类似的表定义设置。我也想到了这一点,但我想的更多的是一个通用问题。我可以很容易地想到其他不特定于日期的示例,因此mysql函数在这种情况下不会有帮助。不过,感谢您的评论!这并不能解决您的主要问题,但如果您是我们的话MySQL然后考虑使用“on更新CurrnTyTimeType”在db级别,其他rdbms可能有类似的表定义设置。我也想到了这一点,但我想的更多的是一个通用问题。我可以很容易地想到其他不特定于日期的示例,因此mysql函数在这种情况下不会有帮助。不过,感谢您的评论!所以您认为存储库实际上可以使用在实体上设置一些属性?对我来说,这样做也很有意义,因为它将集中在一个点上。因为我知道,当用户对象发生更改时,修改的日期应始终更新为当前日期。更改用户对象的唯一方法(当然是持久化)是通过存储库方法save()进行。我知道DDD是关于关注点分离的。你为什么说我把东西弄混了?我不知道我是否理解。我想说的是,你可能有一个有效的理由让
    用户
    对象知道它最后的登录IP是什么,但你关心更新用户以保存它,这一事实告诉我你的要求是l我并不是说
    用户
    知道它的最后一个登录IP是什么,而是系统的其他部分知道。如果是这样的话,那么把最后一个登录IP放在实际需要的地方,让管理登录的服务发布一个用户以某种方式登录的通知。好的。我会接受你的回答,但第二次合作会有更多mment。你也可以用注释更新答案?干杯!谢谢。我会在这个方向上澄清我的答案。那么你是说存储库实际上可以在实体上设置一些属性?这对我来说也是有意义的,因为它将集中在一个点上。因为我知道日期被修改了应始终更新到当前日期
    function save($User) {
    
    if (!$User->id) $User->date_created = 'YYYY-MM-DD HH:II:SS';
    
    $User->date_modified = 'YYYY-MM-DD HH:II:SS';
    
    $DataSource->Save($User);
    
    return $User;
    }