1

ここで述べたように、フォームの選択ボックスで関連オブジェクトを処理するためのカスタム ハイドレーション戦略を構築しています。

私のフォームは次のようになります。

$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\Entity\SecEntity オブジェクト

次に、BasicEntityPersister について何かを説明し、混乱のどこかに私の参照エンティティを示します。

print_r($instance)何も印刷されません。ただ空っぽです。したがって、エラーメッセージは正当だと思います...しかし、これらのオブジェクトを反復処理できないのはなぜですか?

何か案は?

編集:

@サムに関して:

エンティティ内の私の属性:

    /**
 * @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');
        }
    }
4

1 に答える 1

12

私はまだそのためのチュートリアルを書くために来ていません: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;
}

そして、これがすべての魔法が起こっている場所です。SOの他のスレッドにも関連する魔法。まず、 をつかみますEntityManager。次に、フォームを作成し、EntityManager. 私は自分のフォームを使用してこれを行います.Setter-Functionを記述して使用してEntityManager.

次に、 を作成しClassMethodsHydrator、それに 2 つ追加HydrationStrategiesします。個人的には、要素ごとにこれらの戦略を適用する必要がありますObjectSelect。あなたの側でこれを行う必要はないかもしれません。最初にそれなしで機能するかどうかを確認してください!

その後、DoctrineEntity-Hydrator を作成EntityManagerし、カスタムと同様に注入しますClassMethodsHydrator。このようにして、戦略が簡単に追加されます。

残りは一目瞭然です(ドイツ語のクラス名にもかかわらず:D)

なぜ戦略が必要なのか

いも、これは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;
    }
}

したがって、$valueが数値でも null でもない場合はいつでも、つまり、それがオブジェクトである必要がある場合は、getId()関数を呼び出します。個人的には、各要素に独自の戦略を与えるのは良い考えだと思いますが、後で戦略を変更する必要がないと確信している場合は、いくつかの要素のグローバル戦略を作成することもできますDefaultGetIdStrategy.

これは基本的に、BakuraことMichael Gallegoの功績です!IRCに立ち寄る場合は、一度彼を抱きしめてください ;)

編集将来を見据えた追加のリソース- 非常に可能性が高く、すぐに含まれるプルリクエストの更新された hydrator-docs

于 2013-01-03T19:19:08.820 に答える