我正在用ZF2和Doctrine开发一个项目。我试图在表单创建中使用Doctrine Hydrator,如this tutorial所示。在此方法中,在控制器中创建ObjectManager对象,并在实例化时将其传递给新表单。当我想使用ZF2的FormElementManager时,将ObjectManager对象从控制器传递给表单会产生问题,因为ZF2要求我通过Zend \ Form \ FormElementManager获取表单类的实例,而不是直接实例化它。为了解决这个问题,我根据问题How to pass a Doctrine ObjectManager to a form through ZF2 FormElementManager的答案创建了表单和字段集工厂。该问题的答案中提供的方法适用于典型的fieldset元素,但我需要确定如何包含集合元素。本教程使用父字段集中的collection元素中的ObjectManager对象,我需要弄清楚如何使用工厂添加集合。
In [139]: np.index_exp[:]+tuple(ll)
Out[139]: (slice(None, None, None), 1, 2, 3)
In [147]: (np.s_[:],)+tuple(ll)
Out[147]: (slice(None, None, None), 1, 2, 3)
namespace Application\Form;
use Application\Entity\Tag;
use Doctrine\Common\Persistence\ObjectManager;
use DoctrineModule\Stdlib\Hydrator\DoctrineObject as DoctrineHydrator;
use Zend\Form\Fieldset;
use Zend\InputFilter\InputFilterProviderInterface;
class TagFieldset extends Fieldset implements InputFilterProviderInterface
{
public function __construct(ObjectManager $objectManager)
{
parent::__construct('tag');
$this->setHydrator(new DoctrineHydrator($objectManager))
->setObject(new Tag());
$this->add(array(
'type' => 'Zend\Form\Element\Hidden',
'name' => 'id'
));
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'name',
'options' => array(
'label' => 'Tag'
)
));
}
public function getInputFilterSpecification()
{
return array(
'id' => array(
'required' => false
),
'name' => array(
'required' => true
)
);
}
}
namespace Application\Form;
use Zend\Form\Fieldset;
use Application\Entity\Tag;
class TagFieldsetFactory
{
public function __invoke($formElementManager, $name, $requestedName)
{
$serviceManager = $formElementManager->getServiceLocator();
$hydrator = $serviceManager->get('HydratorManager')->get('DoctrineEntityHydrator');
$fieldset = new Fieldset('tags');
$fieldset->setHydrator($hydrator);
$fieldset->setObject(new Tag);
//... add fieldset elements.
$fieldset->add(['...']);
//...
return $fieldset;
}
}
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());
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
$tagFieldset = new TagFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));
}
public function getInputFilterSpecification()
{
return array(
'title' => array(
'required' => true
),
);
}
}
module.config.php中的namespace Application\Form;
use Zend\Form\Fieldset;
use Application\Entity\BlogPost;
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;
}
}
当我添加fieldset元素在我的新BlogPostFieldsetFactory中,我从原始字段集中替换此代码:
'form_elements' => [
'factories' => [
'UpdateBlogPostForm' => 'Application\Form\UpdateBlogPostFormFactory',
'BlogPostFieldset' => 'Application\Form\BlogPostFieldsetFactory',
'TagFieldset' => 'Application\Form\TagFieldsetFactory',
],
],
用这个:
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
如何从原始字段集中替换集合元素:
$fieldset->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
答案 0 :(得分:4)
也许我的问题出错了......但如果你更换了这个
$this->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
这个:
$fieldset->add(array(
'type' => 'Zend\Form\Element\Text',
'name' => 'title'
));
然后你可以替换它:
$tagFieldset = new TagFieldset($objectManager);
$this->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));
用这个:
$tagFieldset = new TagFieldset($objectManager);
$fieldset->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));
现在,如果你不能将$ objectManger传递给表单......好吧,如果你查看代码,你有这个东西可用$ serviceManager,那东西看起来像一个DI容器,我确定你可以得到$ objectManager实例从那里,如果没有,你可以把它的一个实例放在里面。
所以最后的代码可能结束如下:
$objectManager = $serviceManager->get('DoctrineObjectManager') //or something like this
$tagFieldset = new TagFieldset($objectManager);
$fieldset->add(array(
'type' => 'Zend\Form\Element\Collection',
'name' => 'tags',
'options' => array(
'count' => 2,
'target_element' => $tagFieldset
)
));