Zend框架2 - Hydrator关于Doctrine关系的策略不起作用 [英] Zend Framework 2 - Hydrator strategy for Doctrine relationship not working
问题描述
如此处所述,我正在构建一个自定义水合策略,以一种形式的选择框中处理我的相关对象
As mentioned here I'm building a custom hydration strategy to handle my related objects in a select box in a form.
我的表单如下所示:
$builder = new AnnotationBuilder($entityManager);
$form = $builder->createForm(new MyEntity());
$form->add(new MyFieldSet());
$hydrator = new ClassMethodsHydrator();
$hydrator->addStrategy('my_attribute', new MyHydrationStrategy());
$form->setHydrator($hydrator);
$form->get('my_attribute')->setValueOptions(
$entityManager->getRepository('SecEntity\Entity\SecEntity')->fetchAllAsArray()
);
当我添加一个新的 MyEntity
通过 addAction
一切都很好。
When I add a new MyEntity
via the addAction
everything works great.
我写了 fetchAllAsArray )
来填充我的选择框。它存在于我的SecEntityRepository中:
I wrote fetchAllAsArray()
to populate my selectbox. It lives within my SecEntityRepository:
public function fetchAllAsArray() {
$objects = $this->createQueryBuilder('s')
->add('select', 's.id, s.name')
->add('orderBy', 's.name ASC')
->getQuery()
->getResult();
$list = array();
foreach($objects as $obj) {
$list[$obj['id']] = $obj['name'];
}
return $list;
}
但在编辑的情况下, extract()
功能不起作用我不在那里,我看到一些 hydrate()
,所以我现在就把它留下来。
But in the edit-case the extract()
function doesn't work. I'm not at the point where I see something of hydrate()
so I'll leave it out for now.
我的hydrator策略如下所示:
My hydrator strategy looks like this:
class MyHydrationStrategy extends DefaultStrategy
{
public function extract($value) {
print_r($value);
$result = array();
foreach ($value as $instance) {
print_r($instance);
$result[] = $instance->getId();
}
return $result;
}
public function hydrate($value) {
...
}
问题如下:
致命错误:调用成员函数getId( )
Fatal error: Call to a member function getId() on a non-object
print_r($ value)
返回负载以$开头的东西
The print_r($value)
returns loads of stuff beginning with
DoctrineORMModule\Proxy__CG__\SecEntity\Entity\SecEntity Object
DoctrineORMModule\Proxy__CG__\SecEntity\Entity\SecEntity Object
以下是关于BasicEntityPersister的某些东西,而在某些地方,我的引用实体是。
following with something about BasicEntityPersister and somewhere in the mess are my referenced entities.
print_r($ instance)
不打印任何内容。这只是空的因此,我猜是错误信息是合法的...但是为什么我不能迭代这些对象?
The print_r($instance)
prints nothing. It's just empty. Therefore I guess is the error message legit... but why can't I iterate over these objects?
任何想法?
编辑:
关于@Sam:
我的属性在实体中:
/**
* @ORM\ManyToOne(targetEntity="Path/To/Entity", inversedBy="whatever")
* @ORM\JoinColumn(name="attribute_id", referencedColumnName="id")
* @Form\Attributes({"type":"hidden"})
*
*/
protected $attribute;
我的新选择框:
$form->add(array(
'name' => 'attribute',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'attributes' => array(
'required' => true
),
'options' => array(
'label' => 'MyLabel',
'object_manager' => $entityManager,
'target_class' => 'Path/To/Entity',
'property' => 'name'
)
));
我最后的希望是我在控制器内做错了事情。我的选择框都没有被选中,也没有保存这个值...
My final hope is that I'm doing something wrong within the controller. Neither my selectbox is preselected nor the value is saved...
...
$obj= $this->getEntityManager()->find('Path/To/Entity', $id);
$builder = new \MyEnity\MyFormBuilder();
$form = $builder->newForm($this->getEntityManager());
$form->setBindOnValidate(false);
$form->bind($obj);
$form->setData($obj->getArrayCopy());
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$form->bindValues();
$this->getEntityManager()->flush();
return $this->redirect()->toRoute('entity');
}
}
推荐答案
仍然没有到这里写教程:S
I still haven't come around to write the tutorial for that :S
我不知道这是否与注释工具一起使用!由于 DoctrineModule\Form\Element\ObjectSelect
需要 EntityManager
才能正常工作。 ObjectSelect
的选项如下:
I don't know if this is working with the annotationbuilder though! As the DoctrineModule\Form\Element\ObjectSelect
needs the EntityManager
to work. The options for the ObjectSelect
are as follows:
$this->add(array(
'name' => 'formElementName',
'type' => 'DoctrineModule\Form\Element\ObjectSelect',
'attributes' => array(
'required' => true
),
'options' => array(
'label' => 'formElementLabel',
'empty_option' => '--- choose formElementName ---',
'object_manager' => $this->getEntityManager(),
'target_class' => 'Mynamespace\Entity\Entityname',
'property' => 'nameOfEntityPropertyAsSelect'
)
));
在这种情况下,我使用 $ this-> getEntityManager()
。在从ServiceManager调用窗体时,我设置了这种依赖关系。我个人总是从FactoryClasses这样做。我的FormFactory看起来像这样:
In this case i make use of $this->getEntityManager()
. I set up this dependency when calling the form from the ServiceManager. Personally i always do this from FactoryClasses. My FormFactory looks like this:
public function createService(ServiceLocatorInterface $serviceLocator)
{
$em = $serviceLocator->get('Doctrine\ORM\EntityManager');
$form = new ErgebnishaushaltProduktForm('ergebnisform', array(
'entity_manager' => $em
));
$classMethodsHydrator = new ClassMethodsHydrator(false);
// Wir fügen zwei Strategien, um benutzerdefinierte Logik während Extrakt auszuführen
$classMethodsHydrator->addStrategy('produktBereich', new Strategy\ProduktbereichStrategy())
->addStrategy('produktGruppe', new Strategy\ProduktgruppeStrategy());
$hydrator = new DoctrineEntity($em, $classMethodsHydrator);
$form->setHydrator($hydrator)
->setObject(new ErgebnishaushaltProdukt())
->setInputFilter(new ErgebnishaushaltProduktFilter())
->setAttribute('method', 'post');
return $form;
}
这是所有的魔法都在发生的地方。魔术,这也是与你的其他线程在这里相关。首先,我抓住 EntityManager
。然后我创建我的表单,并为 EntityManager
注入依赖项。我使用我自己的表单,你可以写和使用Setter-Function来注入 EntityManager
。
And this is where all the magic is happening. Magic, that is also relevant to your other Thread here on SO. First, i grab the EntityManager
. Then i create my form, and inject the dependency for the EntityManager
. I do this using my own Form, you may write and use a Setter-Function to inject the EntityManager
.
接下来,我创建一个 ClassMethodsHydrator
,并向其添加两个 HydrationStrategies
。个人我需要为每个 ObjectSelect
-Element应用这些策略。您可能不需要在您身边执行此操作。尝试看看它是否工作没有它首先!
Next i create a ClassMethodsHydrator
and add two HydrationStrategies
to it. Personally i need to apply those strategies for each ObjectSelect
-Element. You may not have to do this on your side. Try to see if it is working without it first!
之后,我创建了 DoctrineEntity
-Hydrator,注入 EntityManager
以及我的自定义 ClassMethodsHydrator
。这样一来,策略就会很容易地被添加。
After that, i create the DoctrineEntity
-Hydrator, inject the EntityManager
as well as my custom ClassMethodsHydrator
. This way the Strategies will be added easily.
其余的应该是非常不言自明的(尽管有德文类别:D)
The rest should be quite self-explanatory (despite the german classnames :D)
为什么需要策略
Imo,这是从 DoctrineEntity
,但事情还处于早期阶段。一旦 DoctrineModule-Issue#106 将会生活,事情会再次改变,可能会使它更舒适。
Imo, this is something missing from the DoctrineEntity
currently, but things are still in an early stage. And once DoctrineModule-Issue#106 will be live, things will change again, probably making it more comfortable.
策略如下所示:
<?php
namespace Haushaltportal\Stdlib\Hydrator\Strategy;
use Zend\Stdlib\Hydrator\Strategy\StrategyInterface;
class ProduktbereichStrategy implements StrategyInterface
{
public function extract($value)
{
if (is_numeric($value) || $value === null) {
return $value;
}
return $value->getId();
}
public function hydrate($value)
{
return $value;
}
}
所以每当 $ value
不是数字或空值,意思是:它应该是一个Object,我们将调用 getId()
函数。就个人而言,我认为给每个Element都是自己的策略是一个好主意,但是如果你确定你不需要在以后改变这个策略,你就可以创建一个全局策略,这些元素就像 DefaultGetIdStrategy
或某事。
So whenever the $value
is not numeric or null, meaning: it should be an Object, we will call the getId()
function. Personally i think it's a good idea to give each Element it's own strategy, but if you are sure you won't be needing to change the strategy at a later point, you could create a global Strategy for several elements like DefaultGetIdStrategy
or something.
所有这一切基本上都是 Michael Gallego又名Bakura !如果你放在IRC,只要拥抱他一次;)
All this is basically the good work of Michael Gallego aka Bakura! In case you drop by the IRC, just hug him once ;)
修改另外一个资源,一个查看未来 - 更新的hydrator-docs很可能,很快被包括,拉请求
Edit An additional resource with a look into the future - updated hydrator-docs for a very likely, soon to be included, pull request
这篇关于Zend框架2 - Hydrator关于Doctrine关系的策略不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!