我正在研究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;
}
}
我想将产品分配给一个包,所以我有一个包含选择字段中的产品的表单。 (包装和产品在之前创建)。
表单类型:
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();
// ...
}
//...
}
问题是当我选择产品并提交时,它会将所选产品分配给包,但之前分配的产品将被删除。我希望它们仍然分配,那么如何解决这个问题?
答案 0 :(得分:1)
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,
));
}
}
答案 1 :(得分:0)
尝试向表单添加'by_reference' => false
选项,它将强制使用您实体的setter和getter