Zend框架2 - 保湿战略学说关系不工作(Zend Framework 2 - Hydrator

2019-07-17 19:32发布

如前所述这里我建立一个自定义的水化战略来处理的形式的选择框我的相关对象。

我的形式如下:

$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一切都很正常。

我写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;
}

但是在编辑时的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) {
        ...
    }

问题如下:

致命错误:调用一个成员函数的getId()一个非对象

print_r($value)返回的东西开头的负荷

DoctrineORMModule \ Proxy__CG __ \ SecEntity \实体\ 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;

我的新选择框:

$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'
        )
    ));

我最后的希望是,我做的东西在控制器内是错误的。 无论是我的选择框是预选和值都被保存...

...

$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');
        }
    }

Answer 1:

我还没有来到我身边编写的教程: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'
        )
    ));

在这种情况下,我使用$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;
}

而这正是所有的魔法正在发生的事情。 魔术,这也关系到这里,以便您的其他线程。 首先,我抢EntityManager 。 然后,我创建自己的状态,并注入了依赖EntityManager 。 我这个用我自己的形式,可以编写和使用一个二传手,功能注入做EntityManager

接下来,我创建一个ClassMethodsHydrator并添加两个HydrationStrategies它。 个人而言,我需要办理这些战略对每个ObjectSelect -元素。 你可能没有做到这一点在你的身边。 试试,看看它是否工作没有它第一!

在那之后,我创建DoctrineEntity -Hydrator,注入EntityManager以及我的自定义ClassMethodsHydrator 。 这样的策略会很容易地添加。

其余的应该是相当不言自明的(尽管德国的类名:d)

为什么需要战略

国际海事组织,这是一些人失踪从DoctrineEntity当前,但事情仍处于早期阶段。 而一旦DoctrineModule-问题#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;
    }
}

所以,只要$value不是数字或空,意思是:它应该是一个对象,我们将调用getId()函数。 我个人认为这是一个好主意,让每一个元素,它自己的策略,但如果你确信你不会需要在以后改变策略,您可以创建几个元素,如全球战略DefaultGetIdStrategy什么的。

所有这一切,基本上是良好的工作迈克尔·加列戈又名巴库拉 ! 如果您通过IRC下降,只是拥抱他一次;)

编辑额外的资源以展望未来 -更新水化-docs的一个非常有可能的,很快就被包括在内,要求拉



文章来源: Zend Framework 2 - Hydrator strategy for Doctrine relationship not working