2012-01-19 5 views
4

Я пытаюсь удалить объекты из коллекции, но это не работает.Symfony2 form collection: Как удалить объект из коллекции?

Я думаю, что у меня есть ошибка где-то, но я не знаю, где.

Вот код от моего updateAction:

$em = $this->getDoctrine()->getEntityManager(); 

    $entity = new Person(); 

    if (!$entity) { 
     throw $this->createNotFoundException('Unable to find Person entity.'); 
    } 

    $editForm = $this->createForm(new PersonType(), $entity); 
    $deleteForm = $this->createDeleteForm($id); 

    $request = $this->getRequest(); 

    $editForm->bindRequest($request); 

    if ($editForm->isValid()) { 
     $entity = $editForm->getData(); 

     $em->persist($entity); 
     foreach($entity->getAddresses() as $address) 
     {    
      $em->persist($address); 
     } 
     $em->flush();         

     return $this->redirect($this->generateUrl('person_show', array('id' => $id))); 
    } 

    return $this->render('AppPersonBundle:Person:edit.html.twig', array(
     'entity'  => $entity, 
     'edit_form' => $editForm->createView(), 
     'delete_form' => $deleteForm->createView(), 

    ); 

Обратите внимание, что для удаления моего лица я удалить DIV из HTML.

Я имею в виду, что я удаляю <div id="myapp_personbundle_persontype_address_4">.

Правильно ли это?

ответ

2

В настоящем время, я делаю:

[...]   
    $editForm = $this->createForm(new PersonType(), $entity); 
    $deleteForm = $this->createDeleteForm($id); 

    $previousCollections = array(
     'addresses' => $entity->getAddresses(), 
    );   

    $request = $this->getRequest(); 
    $editForm->bindRequest($request); 

    if ($editForm->isValid()) { 
     $entity = $editForm->getData(); 

     $this->deleteCollections($em, $previousCollections, $entity); 

     $em->persist($entity); 
     foreach($entity->getAddresses() as $address) 
     {    
      $em->persist($address); 
     } 
     $em->flush();         

     return $this->redirect($this->generateUrl('person_show', array('id' => $id))); 
    } 
    [...] 
} 

private function deleteCollections($em, $init, $final) 
{ 
    if (empty($init)) { 
     return; 
    } 

    if (!$final->getAddresses() instanceof \Doctrine\ORM\PersistentCollection) { 
     foreach ($init['addresses'] as $addr) { 
      $em->remove($addr); 
     } 
    } 
} 

И я надеюсь, что решение будет найдено один день с https://github.com/symfony/symfony/issues/1540, но медленно найти.

+0

Большое спасибо, что это мне очень помогает. У меня есть другой вопрос: возможно ли сделать diff между 2 ArrayCollection? – Sam

+0

Не изначально, но с помощью API (http://www.doctrine-project.org/api/common/2.1/doctrine/common/collections/arraycollection.html) вы должны преуспеть – webda2l

+0

правильно ок ... спасибо для всех Сэм – Sam

1

Сбор форм в symfony2 довольно прост, он выполняет почти всю работу за вас. В основном вам просто нужно добавить collection type и установить allow_add, allow_delete флаги и добавить небольшой код JavaScript. Посмотрите на cookbook example

+0

Это должно быть '' 'allow_delete'''''' '' allow_remove''' –

+0

@AcelasiEu Вот почему есть кнопка редактирования на SO ;-) –

13

Благодаря this answer, я нашел лучшее решение. Вы можете использовать Doctrine's orphan removal особенность:

class Gallery 
{ 
    //...  

    /** 
    * @ORM\OneToMany(targetEntity="Photo", mappedBy="gallery", cascade={"persist", "remove"}, orphanRemoval=true) 
    */ 
    private $photos; 

    //... 

    public function removePhotos($photo) 
    { 
     $this->photos->remove($photo); 
     $photo->setGallery(null); 
    } 
} 
0

Я использую это решение ...

В контроллере:

$em = $this->getDoctrine()->getManager(); 
$enity->removeElements($em); 

//Add all your elements again in order to update entity collection. 
$entity->addElement($element) ... 
.... 
$em->persist($entity); 
$em->flush(); 

В сущности:

public function removeElements($em) 
{ 
    $elements = $this->elements; 

    foreach ($elements as $element) { 
     $this->elements->removeElement($element); 
     $em->remove($element); 
     $em->persist($this); 
    } 

} 

Для меня он работает, и он показывает меньше кода, и мне не нужно использовать функцию orphanRemoval.

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