Php 与Symfony'的循环依赖关系;数据映射器模式中的依赖项注入组件

Php 与Symfony'的循环依赖关系;数据映射器模式中的依赖项注入组件,php,symfony,dependency-injection,datamapper,circular-dependency,Php,Symfony,Dependency Injection,Datamapper,Circular Dependency,想象两个实体——用户和组。用户总是在一个组中,而一个组总是有一个超级用户。这些实体类只保存数据(没有逻辑) 这两个实体都有映射器类(处理SQL查询):UserMapper和GroupMapper。查询其实体时,两者相互依赖: 当查询用户以检索用户的$group时,UserMapper需要GroupMapper 当查询组以检索组的$superuser时,GroupMapper需要UserMapper 我一直在使用Symfony的依赖项注入组件在构造函数中注入依赖项。但在这种情况下,我遇到了这种

想象两个实体——用户和组。用户总是在一个组中,而一个组总是有一个超级用户。这些实体类只保存数据(没有逻辑)

这两个实体都有映射器类(处理SQL查询):UserMapper和GroupMapper。查询其实体时,两者相互依赖:

  • 当查询用户以检索用户的$group时,UserMapper需要GroupMapper
  • 当查询组以检索组的$superuser时,GroupMapper需要UserMapper
我一直在使用Symfony的依赖项注入组件在构造函数中注入依赖项。但在这种情况下,我遇到了这种方法的麻烦。我知道我可以使用类似ORM的原则来处理这个问题,但目前还不能选择。这个问题的最干净/最好的解决方案是什么

以下是该计划的说明:


一种可能的方法是引入第三个服务SL并将其注入,如下所示:

  • 映射器是一个接口
  • GroupMapper实现Mapper,通过注入接收SL
  • UserMapper实现映射器,通过注入接收SL
  • SL有以下几种方法:
    • 函数寄存器($name,Mapper m)
    • 函数get($name):映射器
  • GroupMapper::_构造(SL$SL,…)包括以下内容:
    • $this->sl=$sl
    • $this->sl->register('group',$this)
  • UserMapper::_构造(SL$SL,…)包括以下内容:
    • $this->sl=$sl
    • $this->sl->register('user',$this)
然后,假设$um是UserMapper获得DIC的实例,它需要使用组映射器服务:$um->sl->get('user')返回组映射器

本质上,这归结为实现一个服务定位器,这不是很好,但它的优点是它很小,本质上是完整DIC的一个过滤子集。只要在初始化所有相互依赖的服务之前不开始使用任何一个服务,这将起作用,这可能不适合某些情况


另一种可能是使您的服务容器软件和使用它在相同的,但这是更糟的,虽然有点短,因为您基本上允许使用任何从DIC没有任何控制。我建议的模式将“接触面”最小化。

是的,我当时的解决方案基本相同。我花了一些时间考虑它(现在已经一年多了,呵呵),我相信还有第三种解决方案——使用延迟加载代理。我认为最终的解决方案是2阶段setter注入,但这需要修改DI组件源。