Ron*_*Ron 1 php foreign-key-relationship zend-form doctrine-orm zend-framework2
正如这里提到的,我正在构建一个自定义水合策略来处理表单中选择框中的相关对象.
我的表单看起来像这样:
$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()
);
Run Code Online (Sandbox Code Playgroud)
当我添加一个新的MyEntity通过addAction一切都很好.
我写信fetchAllAsArray()填充我的选择框.它存在于我的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;
}
Run Code Online (Sandbox Code Playgroud)
但在编辑案例中,该extract()功能不起作用.我现在还没有看到某些东西,hydrate()所以我现在就把它留下来.
我的保湿策略看起来像这样:
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) {
...
}
Run Code Online (Sandbox Code Playgroud)
问题如下:
致命错误:在非对象上调用成员函数getId()
以... print_r($value)开头的东西的返回负载
DoctrineORMModule\Proxy__CG __\SecEntity\Entity\SecEntity对象
关于BasicEntityPersister的一些内容以及混乱中的某个地方是我引用的实体.
在print_r($instance)打印什么.它只是空的.因此,我猜错误信息是合法的...但为什么我不能迭代这些对象?
有任何想法吗?
编辑:
关于@Sam:
我在实体中的属性:
/**
* @ORM\ManyToOne(targetEntity="Path/To/Entity", inversedBy="whatever")
* @ORM\JoinColumn(name="attribute_id", referencedColumnName="id")
* @Form\Attributes({"type":"hidden"})
*
*/
protected $attribute;
Run Code Online (Sandbox Code Playgroud)
我的新选择框:
$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'
)
));
Run Code Online (Sandbox Code Playgroud)
我最后的希望是我在控制器中做错了什么.我的选择框都没有预先选择,也没有保存值...
...
$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');
}
}
Run Code Online (Sandbox Code Playgroud)
Sam*_*Sam 11
我仍然没有来为此编写教程:S
我不知道这是否适用于annotationbuilder!随着DoctrineModule\Form\Element\ObjectSelect需要的EntityManager工作.选项ObjectSelect如下:
$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'
)
));
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我利用$this->getEntityManager().我从ServiceManager调用表单时设置了此依赖项.我个人总是从FactoryClasses这样做.我的FormFactory看起来像这样:
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;
}
Run Code Online (Sandbox Code Playgroud)
这就是所有魔法发生的地方.魔术,这也与你的其他线程有关.首先,我抓住了EntityManager.然后我创建我的表单,并为其注入依赖项EntityManager.我使用自己的表单执行此操作,您可以编写并使用Setter-Function来注入EntityManager.
接下来我创建一个ClassMethodsHydrator并添加两个HydrationStrategies.我个人需要为每个ObjectSelect元素应用这些策略.您可能没有必要这样做.试着先看看它是否正常工作!
之后,我创建DoctrineEntity-Hydrator,注入EntityManager以及我的自定义ClassMethodsHydrator.通过这种方式,可以轻松添加策略.
其余的应该是不言自明的(尽管德国的名字:D)
为什么需要策略
Imo,这是DoctrineEntity目前缺少的东西,但事情还处于早期阶段.一旦DoctrineModule-Issue#106生效,事情就会再次发生变化,可能会让它变得更加舒适.
战略看起来像这样:
<?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;
}
}
Run Code Online (Sandbox Code Playgroud)
所以每当$value不是数字或null时,意思是:它应该是一个Object,我们将调用该getId()函数.我个人认为给每个元素提供自己的策略是一个好主意,但是如果你确定以后不需要改变策略,你可以为几个元素DefaultGetIdStrategy或类似元素创建一个全局策略.
这一切基本上都是Michael Gallego aka Bakura的好作品!如果你去IRC,只需拥抱他一次;)
编辑一个额外的资源,展望未来 - 更新的hydrator-docs,很快就会包含拉取请求
| 归档时间: |
|
| 查看次数: |
11484 次 |
| 最近记录: |