2015-03-29 4 views
3

Я столкнулся с большим количеством проблем, чем я могу перечислить, пытаясь выяснить, как в & @ # $ * & получить Doctrine, работающий в Zend 2, с формами для заполнения данных , (имеющиеся укусы документации !!!)Zend Framework 2 Form Issues with Doctrine as Hydrator

Я просто пытаюсь заполнить простой список выбора из записей в определенной таблице/Entity. У объекта есть только два свойства. Идентификатор и имя. Я хочу, чтобы значением являлся идентификатор, а текст innerHTML - имя. Нет проблем.

Главный объект, который я пытаюсь написать для формы, называется «Списки» и имеет 3 свойства. ListId, TypeId и ListName. В Доктрине это отношение «Много-к-одному» для объекта «Тип» и «Типы» - это тот, который я хочу использовать для селектора. (свойства: TypeId и TypeName)

Я создал базовую форму и настроил действие контроллера, чтобы получить его через диспетчер службы с помощью FormElementManager. Затем я привязываю его к экземпляру Entity. В конце концов, если ListId предоставлен, я буду извлекать эту запись перед привязкой, но пока я просто создаю новый (пустой) список объектов.

Задача 1:

Сначала я попытался с помощью Fieldset следующего почти линейные для линии из документации ZF2. Когда я создаю свой набор полей с помощью кода обнаружения локатора службы, он получает метод getServiceLocator(), который, как видно из многих ссылок, возвращает FormElementManager в контексте формы. Таким образом, рекомендация заключалась в том, чтобы снова вызвать getServiceLocator() в FormElementManager, чтобы получить фактический локатор службы в Zend. Метод существует, но возвращает «null» из моего Fieldset. У меня как форму, так и FIELDSET, определенный в соответствии с modules.config.php form_elements:

'form_elements' => array(
    'invokables' => array(
     'listForm' => 'Application\Form\ListForm', 
     'typeFieldset' => 'Application\Form\Fieldset\TypeFieldset' 
    ) 
) 

И я ссылаться на FIELDSET из формы (в инициализации() функции) следующим образом:

$this->add(
     array(
      'name' => 'Type', 
      'type' => 'typeFieldset', 
      'options' => array(
       'label' => 'List Type', 
      ), 
      'attributes' => array(
       'required' => 'required' 
      ) 
     ) 
    ); 

Если я не могу добраться до полного диспетчера службы, я не могу использовать Doctrine для правильного заполнения поля.

Задача 2:

я нашел еще один пример, который предложил перейти в сервисе-локатор-Aware код до формы затем использовать доктрину в качестве гидратора. Я получил это на работу и получил поле, заполненное, как я хочу, и получил ярлыки, заполненные надлежащим образом с помощью функции обратного вызова.

$this->add(
     array(
      'name' => 'TypeId', 
      'type' => 'DoctrineORMModule\Form\Element\DoctrineEntity', 
      'options' => array(
       'label'   => 'Type', 
       'object_manager' => $entityManager, 
       'target_class' => 'Application\Entity\Types', 
       'property'  => 'TypeId', 
       'label_generator' => function($targetEntity) { 
        return $targetEntity->getTypeId() . ' - ' . $targetEntity->getTypeName(); 
       }, 
       'display_empty_item' => true, 
       'empty_item_label' => '---', 
       'find_method' => array(
        'name' => 'findBy', 
        'params' => array(
         'criteria' => array(), 
         'orderBy' => array('TypeId' => 'ASC'), 
        ), 
       ), 
      ), 
     ) 
    ); 

Это заставило меня начать игру с ввода идентификатора, чтобы предварительно заполнить форму. Проблема в том, что поле Id тогда является условным и вызывает проблемы, если идентификатор пуст. Я предполагаю, что скрытое поле для Id будет либо нужно установить условным, либо мне как-то нужно будет его разобрать до того, как гидратор попытается сохранить результат. Кажется, я не могу найти документацию о том, как это сделать. В настоящее время я сделал исправление cludge, добавив метод «addId» в форму, которую я могу вызвать из контроллера, если ListId был параметром и является допустимым целым числом, которое соответствует существующей записи.

public function editlistAction() { 
    $listId = $this->params()->fromRoute('id', ''); 

    $form = $this->getForm('listForm'); 

    $list = null; 
    if(!empty($listId) && (intval($listId) > 0)) { 
     $list = $this->getMapper()->findRecordById($listId); 
     $form->addId($listId); // function that adds hidden element 
    } else { 
     $list = new \Application\Entity\Lists(); 
    } 

    $form->bind($list); 

    if ($this->request->isPost()) { 
     // do something with the result 
    } 

    return array(
     'listId' => $listId, 
     'form' => $form 
    ); 
} 

Я тогда только пытаюсь добавить скрытый элемент в представлении, если $ форма-> имеет («ListId») возвращает истину. Есть лучший способ сделать это?

Задача 3:

В представлении, если я только эхо $ this-> FormCollection ($ форма); он отобразит все соответствующие поля, но неформатирован и уродлив. Поэтому я пытался выяснить, как идти по полю, чтобы я мог отформатировать их.

Когда я попытался сделать echo $ this-> formCollection ($ form-> get ('ListId')) (или любое другое имя поля), я продолжаю получать «неопределенный метод» ошибки для типа :: getIterator () (например, неопределенный метод Zend .... \ Hidden :: getIterator()). Итак, я попробовал называть различные декораторы напрямую, такие как: $ this-> formText ($ form-> get ('ListName')); но это уменьшает поле метки. Есть ли хороший пример в любом месте в Интернете, как правильно форматировать форму Zend Framework 2, которая не читается, как свиной латин в греческих гироглифах?

Задача 4:

Так что я прибегал к использованию уродливой формы, чтобы просто посмотреть, смогу ли я получить обратно конец функциональности для работы. Единственное, что я добавил к действию контроллера, это проверить $ form-> isValid() (в настоящее время я не устанавливал никаких валидаторов), и если true, дамп связанного объекта. Когда я это делаю, он снова запутывает - иди цифрой. Кажется, у него проблемы с тем, что один из связанных параметров из формы называется «submit». Нужно ли мне вручную удалять параметры из стандартных элементов формы до гидратации где-то и/или изменять основной предложенный метод exchangeArray() в сущности, чтобы игнорировать их? Шутки в сторону!??!?! Если есть способ удалить их, где? (Я даже не уверен на 100%, в какой момент гидратация на самом деле происходит). А если нет, то как мне избежать этого, чтобы усугубить гидратацию Zend/Doctrine?

.

Я был в этом более 6 часов, у меня открыто около 30 вкладок в моем браузере (не считая 120 или около того, я уже закрыл) и сегодня сделал больше поисковых запросов Google, чем мне хотелось бы вспомнить. Кажется, каждый делает каждый шаг тонко разным, и нет ни одного окончательного источника для хорошего, базового, howto. (Я сидел и молча смотрел на одну страницу документации Zend Framework, которая продолжалась для 80% страницы, просто создавая чрезвычайно хромой набор объектов для описания одного абзаца, как связать его с декоратором, только до того, о ZF1 groan)

Любая помощь будет принята с благодарностью. У меня около 2 дюжин седых волос, у меня кровяное давление около 30 баллов, и мой голос хрипло от крика на мониторе.

ответ

2

Хорошо, прежде всего, когда работа с объектами ORM не обрабатывает ваши ассоциации, как на уровне реляционной БД (т. Е. Этот объект имеет идентификатор другой сущности), но рассматривает их как отношения объекта домена.

Это означает, что наличие объекта $typeId в объекте является неправильным. Вы должны иметь $type тип Type, потому что List имеет-Type, а не typeId.

Во-вторых, внедрение ServiceLocatorAwareInterface является категорически против обесценения. Вы не должны использовать этот интерфейс, если вы не прототипируете, и ваши графики зависимостей пока не определены.
Использовать разгрузку дифференциала конструктора, у вас будет гораздо более чистая структура.

Теперь, как правило, у вас должно быть одно полевое задание на сущность, но ваш пробег может отличаться (для очень простых объектов вы можете просто использовать элемент формы доктрины, как вы на самом деле делаете). Затем вы можете установить набор полей в качестве базового для формы, используя Zend\Form\Fieldset::setUseAsBaseFieldset(), перед добавлением набора полей в форму.

Таким образом, в вашем случае вы бы ListForm с ListFieldset базовой FIELDSET а, которая будет иметь DoctrineEntity поле с именем, установленным в type, значение которого будет отображаться в List::$type по гидратору.

Очевидно, не забудьте установить все гидраторы доктрины соответственно: чтобы установить гидратор базового набора, вы должны вызывать setHydrator() на самой форме после добавления базового набора полей.

Чтобы перебрать элементы формы/набора полей/коллекции, вы можете использовать метод getIterator(), хотя я не вижу никакого элемента коллекции в вашем примере, поэтому неясно, что вы пытаетесь сделать именно с помощью formCollection вид помощник. Элементы Collection предназначены для использования для «многих» сторон отношения, а форма, которую вы описываете, относится к «одной» стороне. Кстати, вы можете просто использовать вспомогательный помощник form или formRow на отдельных элементах, чтобы иметь мелкозернистый контроль над выходом.

Что касается проблемы с скрытым полем идентификатора, поскольку вы уже извлекли его через параметр маршрута, вам фактически не нужна его в форме. ;)

Смежные вопросы