更新多对多关系

Update Many to Many relationship

我正在使用 symfony 3 和 doctrine 进行项目。 我在 Pack 和 Produit 之间有多对多的关系:

包实体:

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);
    }
}

产品实体:

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;
    }
}

我想将产品分配给一个包,所以我有一个在 select 字段中包含产品的表单。 (包装和产品是之前创建的)。

表单类型:

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();
           // ...
        }
       //...
    }

问题是当我 select 产品并提交时,它将 selected 产品分配给包,但之前分配的产品被删除了。我希望他们仍然分配,那么如何解决这个问题?

  • 如果你想让你的视图添加或删除值,如果你手动生成你的字段视图结构,你需要不要忘记填充已经设置的值(例如之前添加到 Pack 的产品)。

例如,将 selected 属性添加到 select 的选项中。这样做会用当前值预填充您的字段,因此在提交时仅删除那些被故意取消选择的值。

  • 如果您不想显示您的视图,也不了解此包上已设置的 Produit 个实体,只是盲目地执行添加,您可以将 mapped => false 添加到您的字段选项并处理手动将您的产品添加到您的控制器中。

这将只允许您添加,因为它不知道已经设置的值,并且您必须再创建一个 case/action 才能执行删除。我认为以上方式更好。

在最后一种情况下,您的控制器看起来像:

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();
       // ...
    }
   //...
}

还有你的表单类型:

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,
        ));
    }
}

尝试向您的表单添加 'by_reference' => false 选项,它将强制使用您实体中的 setter 和 getter