Php 需要从其他对象输入的属性检查应该放在哪里?

Php 需要从其他对象输入的属性检查应该放在哪里?,php,oop,model-view-controller,domain-driven-design,datamapper,Php,Oop,Model View Controller,Domain Driven Design,Datamapper,我试图了解域对象、数据映射器和服务的结构,但是我很难准确地掌握它们的用途 这个问题非常相似,但并没有一个有帮助的答案 需要来自多个对象的属性的方法是否应该进入 域对象,或 服务类,或 都不是 我关心的是创建一个重服务类,但是这种方法似乎比编辑DO和DataMapper更简单,否则我将需要它们 final class UserService extends ServiceAbstract { public function user_is_admin($id) {

我试图了解域对象、数据映射器和服务的结构,但是我很难准确地掌握它们的用途

这个问题非常相似,但并没有一个有帮助的答案

需要来自多个对象的属性的方法是否应该进入

  • 域对象,或
  • 服务类,或
  • 都不是
  • 我关心的是创建一个重服务类,但是这种方法似乎比编辑DO和DataMapper更简单,否则我将需要它们

    final class UserService extends ServiceAbstract
    {
        public function user_is_admin($id)
        {
            // Build the user object
            $userMapper = $this->dataMapperFactory->build('user');
            $user = $this->domainObjectFactory->build('user');
            $user->id = $id;
            $userMapper->fetch($user);
    
            // Build the admin usergroup object
            $usergroup = $this->domainObjectFactory->build('usergroup');
            $usergroupMapper = $this->dataMapperFactory->build('usergroup');
            $usergroup->id = ADMIN_USERGROUP_ID;
            $usergroupMapper->fetch($usergroup);
    
            // Perform the actual check
            if(in_array($user->id, $usergroup->aMembers))
            {
                return true; 
            }
        }
    }
    
    首先,我想到了User.isAdmin()。但在您的例子中,似乎用户和用户组一起决定用户是否是管理员。因此,我们不能将责任归于用户或用户组

    在这种情况下,我通常会引入一个规范对象(对不起,这个示例是用Java编写的)

    因此,域对象不会被不需要的责任损坏,域逻辑仍然保留在域层(而不是应用程序服务中)

    您可以在DDD手册或中找到有关规范模式的更多详细信息


    希望这有帮助。

    首先,IMHO,您执行的授权检查级别错误(请阅读以了解更多详细信息)。另一件事是-您似乎正在从模型层向控制器(或您的区域等效对象)返回数据。这样一个
    boolean
    响应将表明控制器中存在应用程序逻辑出血

    如果你想坚持你目前的结构,那么这样做更有意义:

    class UserService
    {
        // .. snip
        public function someMethod( $id ) 
        {
    
            $userMapper = $this->dataMapperFactory->build('user');
            $groupMapper = $this->dataMapperFactory->build('user');
    
            $user = $this->domainObjectFactory->build('user');
            $user->setId($id);
            $group = $this->domainObjectFactory->build('usergroup');
            $group->setId( UserGroup::ADMIN_GROUP );
    
            $userMapper->fetch($user);
            $groupMapper->fetch($group);
    
    
            return $group->hasUser( $user );
        }
    
    }
    

    我的2美分

    那么在注入usergroup对象后,会从服务类调用AdminSpec.issatifiedby吗?我知道这将如何转移责任,但为这样的检查创建类似乎太过分了,这不仅仅是这个示例,而是由多个对象定义的几乎所有属性。(用户->isAdmin实际上是我在意识到我的错误之前所拥有的。)@birdieblue是否添加额外的规范类完全取决于所获得的优势(解耦)是否值得成本(额外的类)在你的应用程序中。你为什么要破坏
    $user
    $userGroup
    实例的封装?@tereško原谅我的无知,但我不确定我是否理解你的问题,我在破坏什么?@tereško我相信这有点离题,但我假设你想让我写$user->setId($id);是否替换$user->id=$id;?这就是为什么它只是一个评论而不是答案的一部分。使用此方法将意味着两种可能性之一:要么您正在使用域对象参数的可见性
    public
    ,要么您正在使用magic
    \u set()
    方法。这两种方法都会对应用产生阻吓作用。神奇的方法往往会变成复杂的黑洞,
    public
    参数会导致您在完全绕过任何验证和检查的情况下,对域对象中的值何时以及如何更改失去控制。有效的一点是,它确实会流血。这证实了我的直觉,我觉得我的方法有问题。我以前看过你的链接文章,但需要重新访问。我将把授权部分移动到正确的级别,并且在服务类中不再具有此类功能。但是,我可能仍然需要在其他点读取用户的组成员身份(或由多个对象确定的任何其他类似属性)。我认为Hippoom所建议的规范对象将是未来的发展方向。给出你的两个答案,还有其他的意见吗。。有一件事。您当前的方法似乎表明,每个用户只能属于一个组。如果你100%相信这不会改变,就让它保持原样。否则,您可能会考虑在用户和组之间建立
    多对多
    关系。事实恰恰相反,用户可以是许多不同组的一部分。否则,我会直接将组作为用户对象上的属性。不过,我只是以用户和组为例。我遇到的主要问题是,当对象的值由多个对象编译时,如何定义对象的属性。
    class UserService
    {
        // .. snip
        public function someMethod( $id ) 
        {
    
            $userMapper = $this->dataMapperFactory->build('user');
            $groupMapper = $this->dataMapperFactory->build('user');
    
            $user = $this->domainObjectFactory->build('user');
            $user->setId($id);
            $group = $this->domainObjectFactory->build('usergroup');
            $group->setId( UserGroup::ADMIN_GROUP );
    
            $userMapper->fetch($user);
            $groupMapper->fetch($group);
    
    
            return $group->hasUser( $user );
        }
    
    }