Обновить отношения «Многие ко многим» - PullRequest
0 голосов
/ 15 мая 2018

Я работаю над проектом с Symfony 3 и доктриной.У меня много-много отношений между Pack и Produit:

Pack Entity:

class Pack
{ 
    /**
     * @var ArrayCollection | Produit[]
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Produit", inversedBy="packs")
     * @ORM\JoinTable(name="link_pack")
     */
    private $produits;

    public function __construct()
    {
        $this->produits = new ArrayCollection();

    }


    /**
     * @return Produit[]|ArrayCollection
     */
    public function getProduits()
    {
        return $this->produits;
    }

    public function addProduit(Produit $produit)
    {
        if ($this->produits->contains($produit)) {
            return;
        }
        $this->produits[] =  $produit;
    }

    public function removeProduit(Produit $produit)
    {
        if (! $this->produits->contains($produit)) {
            return;
        }
       return $this->produits->removeElement($produit);
    }
}

Produit Entity:

class Produit
{
    /**
     * @var ArrayCollection | Pack[]
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Pack", mappedBy="produits")
     */
    private $packs;

    public function __construct()
    {
        $this->packs = new ArrayCollection();

    }

    /**
     * @return Pack[]|ArrayCollection
     */
    public function getPacks()
    {
        return $this->packs;
    }

    public function addPack(Pack $pack)
    {
        if ($this->packs->contains($pack)) {
            return;
        }
        $pack->addProduit($this);
        $this->packs[] =  $pack;
    }
}

Я хочу назначить продукты для пакета, поэтому у меня есть форма, которая содержит продукты в поле выбора.(пакет и продукты создаются ранее).

Тип формы:

class PackAffectProduitType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('produits', EntityType::class, array(
            'class' => Produit::class,        
            'choice_label' => 'libelle',
                    'multiple' => true,       
        ));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Pack::class,
        ));
    }
}

Контроллер:

public function affectProduitsAction(Pack $pack, Request $request)
    {

        $form = $this->createForm(PackAffectProduitType::class, $pack);

        $form->handleRequest($request);
        dump($pack);
        if ($form->isSubmitted() && $form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            dump($pack);
            $em->flush();
           // ...
        }
       //...
    }

Проблема заключается в том, что я выбираю продукты иотправить, он назначает выбранные продукты пакету, но продукты, назначенные ранее, удаляются.Я хочу, чтобы они все еще назначались, так как решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Попробуйте добавить 'by_reference' => false опцию к вашей форме, это заставит использовать сеттеры и геттеры от вашей сущности

0 голосов
/ 15 мая 2018
  • Если вы хотите, чтобы ваше представление добавляло или удаляло значения, если вы вручную генерируете структуру представления поля, вам не нужно забывать заполнять уже установленные значения (например, продукты, ранее добавленные в Pack).

Например, добавив атрибут selected к выбору вашего select.Это позволит предварительно заполнить ваше поле текущими значениями, поэтому при отправке удаляются только те, которые были преднамеренно не выбраны.

  • Если вы не хотите, чтобы ваш вид отображал или ничего не знал о уже установленных Produit сущностей в этом пакете и просто вслепую выполняйте добавления, вы можете добавить mapped => false к своим полевым параметрам и вручную обработать добавление своих продуктов в свой пакет в своем контроллере.

Это позволит вам толькодобавить, так как он не знает о уже установленных значениях, и вам придется сделать еще один случай / действие, чтобы выполнить удаление.Выше, на мой взгляд, лучше.

В этом последнем случае ваш контроллер будет выглядеть так:

public function affectProduitsAction(Pack $pack, Request $request)
{

    $form = $this->createForm(PackAffectProduitType::class, $pack);

    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        if(is_array($form->get('produits')->getData()){
            foreach($form->get('produits')->getData() as $produit){
                $pack->addProduit($produit);
            }
        }
        $em->flush();
       // ...
    }
   //...
}

И ваш FormType:

class PackAffectProduitType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('produits', EntityType::class, array(
            'class' => Produit::class,     
            'mapped' => false,   
            'choice_label' => 'libelle',
                    'multiple' => true,       
        ));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Pack::class,
        ));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...