Форма Symfony не сохраняет объект с отношением ManyToMany

У меня есть проблема с сохранением сущности с помощью отношений ManyToMany.

Я не могу сохранить поля, которые находятся на стороне «mappedBy».

Код ниже не сохраняет ничего в базе данных и не вызывает никаких ошибок:

// Entity/Pet /** * @var \Doctrine\Common\Collections\Collection * * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Customer", mappedBy="pet", cascade={"persist"}) */ private $customer; /** * Set customer * * @param \AppBundle\Entity\Customer $customer * @return Pet */ public function setCustomer($customer) { $this->customer = $customer; return $this; } // Entity/Customer /** * @var Pet * * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Pet", inversedBy="customer", cascade={"persist"}) * @ORM\JoinTable(name="customer_pet", * joinColumns={ * @ORM\JoinColumn(name="customer_id", referencedColumnName="id") * }, * inverseJoinColumns={ * @ORM\JoinColumn(name="pet_id", referencedColumnName="id") * } * ) */ private $pet; // PetType.php $builder->add('customer', 'entity', array( 'class' => 'AppBundle:Customer', 'property' => 'firstname', 'empty_value' => 'Choose owner', 'multiple' => true )); 

Он работает наоборот. Поэтому, если я что-то сохраняю из CustomerType, все работает.

РЕДАКТИРОВАТЬ:

Решение ниже работало для меня, но через пару дней я нашел проблему с этим решением. Если форма будет отправлена ​​со значением, которое уже было сохранено в базе данных, тогда Symfony вытолкнет ошибку. Чтобы предотвратить, что я должен был проверить, был ли данный клиент уже назначен домашнему животному.

Проверка назначенных клиентов должна была выполняться в начале функции, а не после подачи формы, потому что по какой-то причине после представления объекта Pet () представлены представленные значения не только те, что присутствуют в db.

Поэтому в начале я поместил всех уже назначенных клиентов в массив

  $em = $this->getDoctrine()->getManager(); $pet = $em->getRepository('AppBundle:Pet')->find($id); $petOriginalOwners = array(); foreach ($pet->getCustomer() as $petCustomer) { $petOriginalOwners[] = $petCustomer->getId(); } 

И после отправки формы я проверил, представлены ли представленные идентификаторы в массиве

 if ($form->isValid()) { foreach ($form['customer']->getData()->getValues() as $v) { $customer = $em->getRepository('AppBundle:Customer')->find($v->getId()); if ($customer && !in_array($v->getId(), $petOriginalOwners) ) { $customer->addPet($pet); } } $em->persist($pet); $em->flush(); return $this->redirect($this->generateUrl('path')); } на if ($form->isValid()) { foreach ($form['customer']->getData()->getValues() as $v) { $customer = $em->getRepository('AppBundle:Customer')->find($v->getId()); if ($customer && !in_array($v->getId(), $petOriginalOwners) ) { $customer->addPet($pet); } } $em->persist($pet); $em->flush(); return $this->redirect($this->generateUrl('path')); } 

Solutions Collecting From Web of "Форма Symfony не сохраняет объект с отношением ManyToMany"

В Symfony2 субъект с свойством с комментарием inversedBy доктрины – это тот, который должен ИЗМЕНИТЬ ДОПОЛНИТЕЛЬНЫЙ ТАБЛИЦ, СОЗДАННЫЙ ОТНОШЕНИЕМ MANYTOMANY. Вот почему при создании клиента он вставляет соответствующие строки в эту дополнительную таблицу, сохраняя соответствующих домашних животных.

Если вы хотите, чтобы такое же поведение происходило наоборот, я рекомендую:

 //PetController.php public function createAction(Request $request) { $entity = new Pet(); $form = $this->createCreateForm($entity); $form->submit($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); foreach ($form['customer']->getData()->getValues() as $v) { $customer = $em->getRepository('AppBundle:Customer')->find($v->getId()); if ($customer) { $customer->addPet($entity); } } $em->persist($entity); $em->flush(); return $this->redirect($this->generateUrl('pet_show', array('id' => $entity->getId()))); } return $this->render('AppBundle:pet:new.html.twig', array( 'entity' => $entity, 'form' => $form->createView(), )); } private function createCreateForm(Pet $entity) { $form = $this->createForm(new PetType(), $entity, array( 'action' => $this->generateUrl('pet_create'), 'method' => 'POST', )); return $form; } на //PetController.php public function createAction(Request $request) { $entity = new Pet(); $form = $this->createCreateForm($entity); $form->submit($request); if ($form->isValid()) { $em = $this->getDoctrine()->getManager(); foreach ($form['customer']->getData()->getValues() as $v) { $customer = $em->getRepository('AppBundle:Customer')->find($v->getId()); if ($customer) { $customer->addPet($entity); } } $em->persist($entity); $em->flush(); return $this->redirect($this->generateUrl('pet_show', array('id' => $entity->getId()))); } return $this->render('AppBundle:pet:new.html.twig', array( 'entity' => $entity, 'form' => $form->createView(), )); } private function createCreateForm(Pet $entity) { $form = $this->createForm(new PetType(), $entity, array( 'action' => $this->generateUrl('pet_create'), 'method' => 'POST', )); return $form; } 

Эти два являются стандартными действиями Symfony2 CRUD в контроллере, соответствующими элементу Pet.

Единственная настройка – это структура foreach, вставленная в первое действие, таким образом вы принудительно добавляете одно и то же домашнее животное каждому клиенту, который вы выбираете в форме, тем самым получаете желаемое поведение.

Послушайте, это очень вероятно. Это не ПРАВОЙ ПУТЬ, или ПРАВИЛЬНЫЙ ПУТЬ, но ПУТЬ, и это работает. Надеюсь, поможет.