Zend Framework 2 – стратегия Hydrator для отношений Doctrine не работает

Как уже упоминалось здесь, я создаю специальную стратегию гидратации для обработки связанных объектов в окне выбора в форме.

Моя форма выглядит так:

$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() для заполнения моего selectbox. Он живет в моем 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 Object

следующие с чем-то о 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; 

Мой новый selectbox:

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

Моя последняя надежда состоит в том, что я делаю что-то неправильно в контроллере. Ни мой selectbox не выбран, ни значение не сохраняется …

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

Solutions Collecting From Web of "Zend Framework 2 – стратегия Hydrator для отношений Doctrine не работает"

Я все еще не пришел, чтобы написать учебник для этого: S

Я не знаю, работает ли это с аннотацией! Поскольку 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; } 

И здесь происходит вся магия. Magic, что также актуально для вашей другой темы здесь, на SO. Во-первых, я хватаю EntityManager . Затем я создаю свою форму и добавляю зависимость для EntityManager . Я делаю это, используя свою собственную форму, вы можете написать и использовать Setter-Function для инъекции EntityManager .

Затем я создаю ClassMethodsHydrator и добавляю к нему две системы ClassMethodsHydrator . Лично мне нужно применить эти стратегии для каждого ObjectSelect -Element. Возможно, вам не придется делать это на вашей стороне. Попытайтесь увидеть, работает ли он без него в первую очередь!

После этого я создаю 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; } } 

Поэтому всякий раз, когда $value не является числовым или нулевым, это означает: он должен быть объектом, мы будем называть getId() . Лично я считаю, что это хорошая идея дать каждому элементу собственную стратегию, но если вы уверены, что вам не понадобится менять стратегию на более позднем этапе, вы можете создать глобальную стратегию для нескольких элементов, таких как DefaultGetIdStrategy или что-то еще.

Все это в основном хорошая работа Майкла Гальего, ака Бакуры ! Если вы бросите IRC, просто обними его один раз;)

Редактировать Дополнительный ресурс с учетом будущего – обновленные гидратор-документы для очень вероятного, вскоре будут включены, запрос на pull