如何通过 ZF2 FormElementManager 将 Doctrine ObjectManager 传递给表单
Posted
技术标签:
【中文标题】如何通过 ZF2 FormElementManager 将 Doctrine ObjectManager 传递给表单【英文标题】:How to pass a Doctrine ObjectManager to a form through ZF2 FormElementManager 【发布时间】:2015-12-31 22:04:04 【问题描述】:我想在 ZF2 中创建自定义表单元素,这需要 FormElementManager。我目前在表单创建中使用 Doctrine Hydrator,如this tutorial 所示。在该方法中,在控制器中创建一个 ObjectManager 对象,并在实例化时传递给新表单:
public function editAction()
// Get your ObjectManager from the ServiceManager
$objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager');
// Create the form and inject the ObjectManager
$form = new UpdateBlogPostForm($objectManager);
// …
更新表格:
namespace Application\Form;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Form;
class UpdateBlogPostForm extends Form
public function __construct(ObjectManager $objectManager)
parent::__construct('update-blog-post-form');
// The form will hydrate an object of type "BlogPost"
$this->setHydrator(new DoctrineHydrator($objectManager));
// Add the user fieldset, and set it as the base fieldset
$blogPostFieldset = new BlogPostFieldset($objectManager);
$blogPostFieldset->setUseAsBaseFieldset(true);
$this->add($blogPostFieldset);
// … add CSRF and submit elements …
// Optionally set your validation group here
BlogPost 字段集:
namespace Application\Form;
use Application\Entity\BlogPost;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
class BlogPostFieldset extends Fieldset implements InputFilterProviderInterface
public function __construct(ObjectManager $objectManager)
parent::__construct('blog-post');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new BlogPost());
// … add fieldset elements …
// … public function getInputFilterSpecification() …
不幸的是,为了使用 ZF2 的 FormElementManager,ZF2 manual 说,“第二个问题是你不能直接实例化你的表单类,而是通过 Zend 获取它的实例\Form\FormElementManager;"所以我必须得到这样的表格:
public function editAction()
$sl = $this->getServiceLocator();
$form = $sl->get('FormElementManager')->get('\Application\Form\UpdateBlogPostForm');
有没有办法通过FormElementManager
将ObjectManager 对象$objectManager
传递给表单,或者有没有办法在表单中创建对象以便水合器和字段集可以使用它?
【问题讨论】:
【参考方案1】:DoctrineEntityHydratorFactory
创建 hydrator 并注入对象管理器的工厂。
namespace MyModule\Stdlib\Hydrator;
use DoctrineORMModule\Stdlib\Hydrator\DoctrineEntity;
class DoctrineEntityHydratorFactory
public function __invoke($hydratorPluginManager, $name, $requestedName)
$serviceManager = $hydratorPluginManager->getServiceLocator();
$objectManager = $serviceManager->get('Doctrine\ORM\EntityManager');
return new DoctrineEntity($objectManager);
博客帖子字段集
一个可重用的字段集,其中包含博客文章的所有元素,并使用 EntityHydrator
来补充 BlogPost
实体。
namespace MyModule\Form;
use Zend\Form\Fieldset;
class BlogPostFieldsetFactory
public function __invoke($formElementManager, $name, $requestedName)
$serviceManager = $formElementManager->getServiceLocator();
$hydrator = $serviceManager->get('HydratorManager')->get('DoctrineEntityHydrator');
$fieldset = new Fieldset('blog_post');
$fieldset->setHydrator($hydrator);
$fieldset->setObject(new BlogPost);
//... add fieldset elements.
$fieldset->add(['...']);
//...
return $fieldset;
UpdateBlogPostFormFactory
创建博客文章更新表单的工厂。这会附加字段集并设置the use_as_base_fieldset
option which allows it to use the fieldsets hydrator。
namespace MyModule\Form;
class UpdateBlogPostFormFactory
public function __invoke($formElementManager, $name, $requestedName)
$form = new Form('update_blog_post);
//...
$factory = new \Zend\Form\Factory($formElementManager);
$form->setFormFactory($factory);
$form->add([
'name' => 'blog_post',
'type' => 'BlogPostFieldset',
'options' => [
'use_as_base_fieldset' => true,
]
]);
//...
return $form;
您还需要在module.config.php
中向所需经理注册服务。
return [
'form_elements' => [
'factories' => [
'UpdateBlogPostForm' => 'MyModule\Form\UpdateBlogPostFormFactory',
'BlogPostFieldset' => 'MyModule\Form\BlogPostFieldsetFactory',
],
],
'hydrators' => [
'factories' => [
'DoctrineEntityHydrator' => 'MyModule\Stdlib\Hydrator\DoctrineEntityHydratorFactory',
],
],
];
因此,您可以在控制器中请求您的表单。
$form = $formElementManager->get('UpdateBlogPostForm');
【讨论】:
谢谢,@AlexP。在实施您的解决方案时,我发现我的问题并不彻底。在我试图解决的 Doctrine hydrator 模型中,ObjectManager 对象$objectManager
也用于将字段集注入表单。我已经扩展了我的问题以表明这一点。现在是否应该将字段集注入到EditProjectPhaseFactory
的表单中?怎么样?
@jcropp 如果您有多个表单(更新/创建/编辑),您可以创建一个可重用的字段集,如我的编辑所示。这个字段集实际上是水化的,您只需要将它附加到每个表单。
我不断收到错误消息:Zend\ServiceManager\Exception\ServiceNotFoundException
文件为…\vendor\zendframework\zendframework\library\Zend\ServiceManager\ServiceManager.php:529
,消息为Zend\Form\FormElementManager::get was unable to fetch or create an instance for BlogPostFieldset
,堆栈跟踪的最后一行为…\vendor\zendframework\zendframework\library\Zend\ServiceManager\AbstractPluginManager.php(103): Zend\ServiceManager\ServiceManager->get('BlogPostFieldse...', true)
。有什么想法吗?
我检查了所有的拼写并尝试用小写重命名以排除命名问题。
我已添加到表单工厂;你也可以使用$form->add($formElementManager->get('BlogPostFieldset))'
以上是关于如何通过 ZF2 FormElementManager 将 Doctrine ObjectManager 传递给表单的主要内容,如果未能解决你的问题,请参考以下文章