Doctrine Symfony与领域驱动设计

Doctrine Symfony与领域驱动设计,doctrine,domain-driven-design,symfony,Doctrine,Domain Driven Design,Symfony,在Symfony 3中,您如何根据域驱动设计(DDD)区分以下内容 服务(在配置服务文件中定义的服务) 条令存储库(\条令\ORM\EntityRepository) 实体(实体文件夹中的类) 我知道条令与Symfony是分离的(也就是说,它可以完全省略)。但是,在没有条令的Symfony项目中,哪一个是存储库?或者Symfony(没有学说)实际上没有真正遵循DDD 编辑 为了让我的问题更清楚,我尝试模拟下面的场景 控制器具有返回项目所有可用经理的功能 class ManagementCon

在Symfony 3中,您如何根据域驱动设计(DDD)区分以下内容

  • 服务(在配置服务文件中定义的服务)
  • 条令存储库(\条令\ORM\EntityRepository)
  • 实体(实体文件夹中的类)
我知道条令与Symfony是分离的(也就是说,它可以完全省略)。但是,在没有条令的Symfony项目中,哪一个是存储库?或者Symfony(没有学说)实际上没有真正遵循DDD

编辑

为了让我的问题更清楚,我尝试模拟下面的场景

控制器具有返回项目所有可用经理的功能

class ManagementController
    public function getAvailableManagers(Array $project)
    {
        ...
    }
}    
可用经理意味着他们手头没有项目,项目属于他们的专业领域(如客户服务、业务关系、物流等)

但是,由于设计不当,专业域未存储在数据库中,而是需要通过API调用调用到单独的人力资源系统。稍后,它将集成到数据库中

我会认为(请随意更正)Manager应该是一个repository类,因为它当前从两个不同的来源获取信息。问题是。。。我应该为此使用条令存储库吗?或者它应该只是一个普通的实体或者一个服务

class ReplacementInstructionRepository extends \Doctrine\ORM\EntityRepository
{
    private $id;
    private $name;
    private $speciality;
    private $projects;
}
我需要一个关于如何分割的指南。多谢各位


干杯,

尽管我不太理解这个问题,但这里有一些将DDD原则应用于Symfony的项目示例

编辑

在你最后一次描述之后,我想我可以给出一个更好的答案:-)

我想说的是,这很符合你的设想。规范模式允许您在域层中保留业务规则。在本例中,您提到了一条重要的业务规则:

可用经理意味着他们手头没有项目,项目属于他们的专业领域(如客户服务、业务关系、物流等)

在本例中,您提到了我们需要处理的一个糟糕的设计。在一个绿地项目中,我会在管理者中保存管理者的专业领域,这样所有的东西都会存在于同一个聚合根(管理者)中

在您的情况下,我将通过存储库集成外部方(人力资源系统),如下所示:

nampespace xxx\infrastructure\persistence
class ManagersRepository
{
    public function __construct(HrApiClient $apiClient)
    {
        $this->apliClient = $apiClient;
    }

    public function findWithoutProjects()
    {
        $sqlQuery = //find all managers without project
        $managers = $this->execute($sqlQuery);
        foreach ($managers as $manager) {
            $projects = $this->apliClient->findProjectsOfManagerId($manager->id());
            $manager->specialisedIn($projects); //This should be done with reflection
        }

        return $managers;
    }

    public function selectSatisfying(Specification $specification)
    {
        return $specification->satisfyingElementsFrom($this);
    }
}

namespace xxx\Domain
class ManagersAvailableSpecification implements Specification
{
    public function __construct($aNewProject)
    {
        $this->aNewProject = $aNewProject;
    }

    public function isSatisfiedBy($manager)
    {
        // business rules here...
        if ($manager->isSpecialisedIn($this->aNewProject)) {
            return true;
        }

        return false;
    }

    public function satisfyingElementsFrom(ManagersRepository $managersRepository)
    {
        $managers = $managersRepository->findWithoutProjects();

        return array_filter(
            $managers,
            function (Manager $manager) {
                return $this->isSatisfiedBy($manager);
            }
        );
    }
}
请注意,第一个类是存储库的具体实现(使用MySql、Postgre等),它位于基础结构层。而第二个,因为它仅依赖于接口,所以它与定义可用管理器的业务规则一起存在于域中

现在,您可以享受以下服务:

class FindAvailableManagersService
{
    private $managersRepository;

    public function __construct(ManagersRepository $managersRepository)
    {
        $this->managersRepository = $managersRepository;
    }

    public function execute(FindAvailableManagersRequest $request)
    {
        $managersAvailable = $this->managersRepository->selectSatisfying(
            new ManagersAvailableSpecification($request->project())
        );

        return $managersAvailable;
    }
}
还要注意的是,如果将来您将专用域从第三方迁移到自己的数据库中,您只需要修改一个类,而不会涉及其他任何类:-)

问题是。。。我应该为此使用条令存储库吗

我认为这是与DDD有关的最典型的误解。ORM响应和实体与DDD存储库和实体完全不同。他们只是有相同的名字,但仅此而已,你不应该混淆他们


DDD实体位于域中,不依赖于域外的类。DDD存储库接口在域中定义,实现在基础架构中,可以依赖于基础架构的其他部分。因此,要实现DDD存储库接口,如果您愿意,您可以使用ORM存储库,但您可以使用与关系数据库完全不同的数据存储解决方案,例如noSQL数据库。

您为什么认为Symfony with Doctrine遵循DDD?大多数Symfony应用程序都是crud应用程序。如果适用,您可以使用Symfony遵循DDD的一些原则。你写的问题对我来说毫无意义。谢谢你的反馈,我已经用示例场景更新了问题。希望它能消除困惑:)我更新了我的答案,提供了更多细节。希望你觉得它有用。有趣。。。因此,您的存储库没有使用条令存储库(
\doctor\ORM\EntityRepository
),而是为存储库使用普通类。这是因为条令存储库无法投入使用,因此无法注入?谢谢