F
F
freeentr2014-09-09 12:05:32
Doctrine ORM
freeentr, 2014-09-09 12:05:32

How to properly save Zend\Form + Doctrine 2 data?

Greetings!
I study ZF2+Doctrine 2.
The situation is as follows:
1) There is a set of entities to manage the User's data.
down.php?i=rtmufdy&view
2) Zend\Form + Fieldset
The form consists of 2 sets of fields, Primary (Entity\User) and Secondary (Entity\UserInfo). They have a structure according to the documentation.

function __construct( ObjectManager $objectManager ) {

        parent::__construct('ProfileEdit');

        $this->setName('ProfileEdit');
        $this->setAttribute('method', 'post');

// objectManager = $this->getServiceLocator()->get('Doctrine\ORM\EntityManager')
        $this->setHydrator(new DoctrineHydrator($objectManager));

        $userFieldset = new UserBasicFieldset($objectManager);
        $userFieldset->setUseAsBaseFieldset(true);
        $this->add($userFieldset);

        $userInfoFieldset = new UserInfoFieldset($objectManager);
        $this->add($userInfoFieldset);

        $this->add(array(
            'type' => 'Zend\Form\Element\Csrf',
            'name' => 'security'
        ));

        $this->add(array(
            'name'       => 'submit',
            'attributes' => array(
                'type'  => 'submit',
                'value' => 'Save',
            )
        ));
    }

3) The controller
is also quite simple
if ($this->zfcUserAuthentication()->hasIdentity()) {

            $userId        = $this->zfcUserAuthentication()->getIdentity()->getId();
            $objectManager = $this->getOrmEntityManager();
            $form          = new ProfileEditForm($objectManager);
            $user          = $objectManager->find('User\Entity\User', $userId);

            $form->bind($user);

            if ($this->request->isPost()) {

                $form->setData($this->request->getPost());

                if ($form->isValid()) {

                    $objectManager->flush();
                }
            }

            return new ViewModel(array(
                'form' => $form
            ));
        }

If I don't add a Secondary (Entity\UserInfo) fieldset to the form, then output and save work as they should. Otherwise, only output works.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Shirshov Alexander, 2014-10-22
@Keanor

Что за DoctrineHydrator? Я у себя только DoctrineObject нашел, всегда его и использовал.
Как происходит гидрация через DoctrineObject - Doctrine получает метадату для сущности которую вы гидрируете, и итерируясь по массиву переданому в hydrate обрабатывает только записи ключи которых есть в св-вах сущности. При обработки каждого ключа массива гидратор проверяет - связь ли это, и если связь то какая: в нём есть два метода для гидрации данных по связям: toOne() и toMany(), так как у вас судя по схеме ManyToMany вызовется метод toMany(), я его сюда скопирую:

// If the collection contains identifiers, fetch the objects from database
        foreach ($values as $value) {
            if ($value instanceof $target) {
                $collection[] = $value;
            } elseif ($value !== null) {
                $targetObject = $this->find($value, $target);

                if ($targetObject !== null) {
                    $collection[] = $targetObject;
                }
            }
        }

As you can see, it can only work with 2 types of data:
1) with an ID set (then it searches for the entity itself and makes connections)
2) with an entity set
In your case, a set of arrays is passed, so it does not work.
To make it work, you need to use a hydrator, including for Fieldset, then at the moment when the main form is hydrated, the elements will already be hydrated, and instead of an array of arrays, toMany() will receive an array of entities.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question