ZF2 Doctrine - 如何处理需要特定 id 的依赖注入
ZF2 Doctrine - How to handle dependency injection which requires a certain id
我不确定如何提出问题,请随时编辑。
我目前的情况是这样的:
我有一个实例化表单 class 的工厂 class。依赖注入(DI)是通过构造函数注入完成的。我的问题是,这个表单元素有一个 Doctrine ObjectMultiCheckbox,它需要一个 findby 方法。对于这个 findby 方法,我需要某个实体的 ID,但我无法通过工厂 class 将 ID 传递给表单。
我的问题是,我该如何处理这种情况?什么是最好的方法?
假设这是我的工厂class:
class CustomerFormFactory implements FactoryInterface
{
/**
* Create service
*
* @param ServiceLocatorInterface $serviceLocator
* @return Form
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$em = $serviceLocator->get('Doctrine\ORM\EntityManager');
return new CustomerForm($em);
}
}
我通过这样的服务定位器获取表单:
$customerForm = $this->getServiceLocator()->get('CustomerForm');
如何将 ID 传递给服务定位器?而如果表单元素需要某个ID,那岂不是破坏了DI和服务的目的?我是否应该采用 "classic" 方式并像这样自己实例化表单元素:
$customerForm = new CustomerForm(EntityManager $em, int $id);
我真的不确定我应该做什么或者处理这个问题的最佳方法是什么。
为了将选项插入到您的表单中,您可以使用工厂 class 的 CreationOptions
。
所以让我们开始为 FormElementManager(我们的表单元素的 serviceLocator)设置我们的配置。
在你的 Module.php
内:
use Zend\ModuleManager\Feature\FormElementProviderInterface;
class Module implements FormElementProviderInterface
{
// your module code
public function getFormElementConfig()
{
return [
'factories' => [
'myForm' => \Module\Form\MyFormFactory::class
]
];
}
}
设置配置后,我们应该创建我们的工厂,returns 表单包括它的依赖项。我们还在表单 class.
中插入了可以重复使用的选项
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\MutableCreationOptionsTrait;
use Zend\ServiceManager\ServiceLocatorInterface;
class MyFormFactory implements FactoryInterface
{
use MutableCreationOptionsTrait;
/**
* Create service
*
* @param ServiceLocatorInterface $serviceLocator
*
* @return mixed
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new MyForm(
$serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager'),
'MyForm',
$this->getCreationOptions()
);
}
}
When using ZF3 it is better to use \Zend\ServiceManager\Factory\FactoryInterface
instead of the \Zend\ServiceManager\FactoryInterface
as this is the way ZF3 is going with using factories. In the example above I used the ZF2 (v2.7.6 zendframework/zend-servicemanager) version. See the comment on the class Zend\ServiceManager\FactoryInterface::class to replace it with the ZF3 version.
所以现在当我们在 FormElementManager
class 上调用 ::get('myForm', ['id' => $id])
时,您将获得一个 MyForm
实例并且表单的选项将包含我们已经设置的选项传了。
因此您的表单可能看起来类似:
class MyForm extends \Zend\Form\Form
{
public function __construct(
\Doctrine\Common\Persistence\ObjectManager $entityManager,
$name = 'myForm',
$options = []
) {
parent::__construct($name, $options);
$this->setEntityManager($entityManager);
}
public function init () {
/** add form elements **/
$id = $this->getOption('id');
}
}
您也可以创建表单并设置实体管理器,但这完全取决于您。您不需要使用构造函数注入。
你的控制器的例子:
$myForm = $this->getServiceManager()->get('FormElementManager')->get('myForm', ['id' => 1337]);
$options = $myForm->getOptions();
// your options: ['id' => 1337]
当您使用 ZF2.5+ 或 ZF3 时,您的 Controller 中可能没有 ServiceManager 或 Locator,因此您必须通过工厂将 FormElementManager 或 Form class 注入到您的 Controller 中。
如果您的表单中没有任何其他依赖项,但您想要设置选项,则不需要为每个 class 创建一个工厂。您可以重新使用 InvokableFactory::class
因为这也会注入 creationOptions.
我不确定如何提出问题,请随时编辑。
我目前的情况是这样的: 我有一个实例化表单 class 的工厂 class。依赖注入(DI)是通过构造函数注入完成的。我的问题是,这个表单元素有一个 Doctrine ObjectMultiCheckbox,它需要一个 findby 方法。对于这个 findby 方法,我需要某个实体的 ID,但我无法通过工厂 class 将 ID 传递给表单。
我的问题是,我该如何处理这种情况?什么是最好的方法?
假设这是我的工厂class:
class CustomerFormFactory implements FactoryInterface
{
/**
* Create service
*
* @param ServiceLocatorInterface $serviceLocator
* @return Form
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
$em = $serviceLocator->get('Doctrine\ORM\EntityManager');
return new CustomerForm($em);
}
}
我通过这样的服务定位器获取表单:
$customerForm = $this->getServiceLocator()->get('CustomerForm');
如何将 ID 传递给服务定位器?而如果表单元素需要某个ID,那岂不是破坏了DI和服务的目的?我是否应该采用 "classic" 方式并像这样自己实例化表单元素:
$customerForm = new CustomerForm(EntityManager $em, int $id);
我真的不确定我应该做什么或者处理这个问题的最佳方法是什么。
为了将选项插入到您的表单中,您可以使用工厂 class 的 CreationOptions
。
所以让我们开始为 FormElementManager(我们的表单元素的 serviceLocator)设置我们的配置。
在你的 Module.php
内:
use Zend\ModuleManager\Feature\FormElementProviderInterface;
class Module implements FormElementProviderInterface
{
// your module code
public function getFormElementConfig()
{
return [
'factories' => [
'myForm' => \Module\Form\MyFormFactory::class
]
];
}
}
设置配置后,我们应该创建我们的工厂,returns 表单包括它的依赖项。我们还在表单 class.
中插入了可以重复使用的选项use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\MutableCreationOptionsTrait;
use Zend\ServiceManager\ServiceLocatorInterface;
class MyFormFactory implements FactoryInterface
{
use MutableCreationOptionsTrait;
/**
* Create service
*
* @param ServiceLocatorInterface $serviceLocator
*
* @return mixed
*/
public function createService(ServiceLocatorInterface $serviceLocator)
{
return new MyForm(
$serviceLocator->getServiceLocator()->get('Doctrine\ORM\EntityManager'),
'MyForm',
$this->getCreationOptions()
);
}
}
When using ZF3 it is better to use
\Zend\ServiceManager\Factory\FactoryInterface
instead of the\Zend\ServiceManager\FactoryInterface
as this is the way ZF3 is going with using factories. In the example above I used the ZF2 (v2.7.6 zendframework/zend-servicemanager) version. See the comment on the class Zend\ServiceManager\FactoryInterface::class to replace it with the ZF3 version.
所以现在当我们在 FormElementManager
class 上调用 ::get('myForm', ['id' => $id])
时,您将获得一个 MyForm
实例并且表单的选项将包含我们已经设置的选项传了。
因此您的表单可能看起来类似:
class MyForm extends \Zend\Form\Form
{
public function __construct(
\Doctrine\Common\Persistence\ObjectManager $entityManager,
$name = 'myForm',
$options = []
) {
parent::__construct($name, $options);
$this->setEntityManager($entityManager);
}
public function init () {
/** add form elements **/
$id = $this->getOption('id');
}
}
您也可以创建表单并设置实体管理器,但这完全取决于您。您不需要使用构造函数注入。
你的控制器的例子:
$myForm = $this->getServiceManager()->get('FormElementManager')->get('myForm', ['id' => 1337]);
$options = $myForm->getOptions();
// your options: ['id' => 1337]
当您使用 ZF2.5+ 或 ZF3 时,您的 Controller 中可能没有 ServiceManager 或 Locator,因此您必须通过工厂将 FormElementManager 或 Form class 注入到您的 Controller 中。
如果您的表单中没有任何其他依赖项,但您想要设置选项,则不需要为每个 class 创建一个工厂。您可以重新使用 InvokableFactory::class
因为这也会注入 creationOptions.