Dependency injection 如何将ObjectManager正确地注入到字段集中?

Dependency injection 如何将ObjectManager正确地注入到字段集中?,dependency-injection,doctrine-orm,zend-framework2,entitymanager,fieldset,Dependency Injection,Doctrine Orm,Zend Framework2,Entitymanager,Fieldset,我正在努力将Doctrine的ObjectManager正确地注入到我的字段集。我不想把它传递给所有的构造函数。情况如下: 控制器: 控制器没有ObjectManager 控制器使用服务 服务: 服务实现ObjectManagerWare接口 服务通过初始值设定项类获取ObjectManager 服务提供表格 表格: 表单不应该有ObjectManager——至少到目前为止,它们还不需要ObjectManager 表单创建相应的字段集 字段集: 字段集实现ObjectManager

我正在努力将Doctrine的ObjectManager正确地注入到我的字段集。我不想把它传递给所有的构造函数。情况如下:

控制器:

  • 控制器没有ObjectManager
  • 控制器使用服务
服务:

  • 服务实现ObjectManagerWare接口
  • 服务通过初始值设定项类获取ObjectManager
  • 服务提供表格
表格:

  • 表单不应该有ObjectManager——至少到目前为止,它们还不需要ObjectManager
  • 表单创建相应的字段集
字段集:

  • 字段集实现ObjectManagerWare接口
现在,我将ObjectManager服务传递到表单字段集。这种做法非常丑陋

我知道有一个使用FormElementManager的解决方案。但是为了做到这一点,我必须通过注入ServiceLocator来为表单提供访问ServiceLocator的权限。这种方法似乎并不比我目前的方法更合适

问题是如何将Doctrine的ObjectManager注入到我的字段集中,而不将全局ServiceLocator(或其他东西)注入到我的表单中。如果可能的话,我想让表格保持简单

下面大致显示了我的应用程序现在是如何构建的:

abstract class AbstractService implements ObjectManagerAwareInterface
{

    private $objectManager;

    public function getObjectManager()
    {
        return $this->objectManager;
    }

    public function setObjectManager(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;

        return $this;
    }

}

class MyService extends AbstractService
{

    public function doSomething()
    {
        $count = $this->someCalculation();
        $myForm = new MyForm($count, $this->getObjectManager());

        // ...
    }

}

class MyForm extends Form
{

    private $objectManager;

    public function __construct($count, ObjectManager $objectManager) // TODO: Remove $objectManager
    {
        parent::__construct('myForm');

        $this->objectManager = $objectManager;

        $myCollection = new Collection('myCollection');
        $myCollection->setCount($count);
        $myCollection->setTargetElement(new MyFieldset($objectManager)); // TODO: ???
        $myCollection->setUseAsBaseFieldset(true);
        $this->add($myCollection);

        $submit = new Submit('submit');
        $this->add($submit);
    }
}

abstract class AbstractFieldset extends Fieldset
                                implements ObjectManagerAwareInterface
{

    private $objectManager;

    public function getObjectManager()
    {
        return $this->objectManager;
    }

    public function setObjectManager(ObjectManager $objectManager)
    {
        $this->objectManager = $objectManager;

        return $this;
    }

}

class MyFieldset extends AbstractFieldset
{

    public function __construct(ObjectManager $objectManager) // TODO: Remove $objectManager
    {
        parent::__construct('myFieldset');

        $this->setObjectManager($objectManager); // TODO: Use initializer

        $this->setHydrator(new DoctrineObject($this->getObjectManager(), true));
        $this->setObject(new MyModel());

        // ...
    }
}

基本上,您应该使用
FormElementManager

// Config array
'form_elements' => [
    'factories' => [
        'My\Cool\Fieldset' => 'My\Cool\FieldsetFactory'
    ]
]
然后你有异常的工厂课程

class FieldsetFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $sl)
    {
        $realServiceLocator = $sl->getServiceLocator();
        $entityManager      = realServiceLocator->get('Doctrine\ORM\EntityManager');

        return new \My\Cool\Fieldset($entityManager);
    }
}

这将是最合适的方法。

+1我想补充一点,如果通过表单中的
$this->add()
添加字段集,则该字段集可以通过
FormFactory
访问
FormElementManager
(因此无需插入服务定位器)