如何配置Symfony3表单类型的多对多关联?
在Symfony3中配置带有多对多关联的表单类型
要搞定Symfony3里多对多关联的表单配置,核心是用EntityType字段,并配合正确的选项设置——当然前提是你已经在实体类里完成了多对多的映射配置。下面我结合你的示例代码,一步步拆解说明:
完整的ProductType表单类示例
// src/AppBundle/Form/Type/ProductType.php namespace AppBundle\Form\Type; use AppBundle\Entity\ShopProductImages; use Doctrine\ORM\EntityRepository; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\TextareaType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Bridge\Doctrine\Form\Type\EntityType; class ProductType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name') // 绑定Product实体的name属性 ->add('price') // 绑定price属性 ->add('description', TextareaType::class) // 用文本域展示description ->add('quantity') // 绑定quantity属性 ->add('shopProductImages', EntityType::class, [ 'class' => ShopProductImages::class, // 指定关联的实体类 'choice_label' => 'file', // 下拉/复选框里显示实体的file字段值 'query_builder' => function (EntityRepository $repo) { // 自定义查询,只选id大于1的图片 return $repo->createQueryBuilder('f') ->where('f.id > :id') ->setParameter('id', 1); }, 'multiple' => true, // !重点! 多对多必须开启这个,允许选择多个实体 'expanded' => false, // false为下拉多选,true为复选框组,按需选择 ]); } }
关键配置点解析
multiple: true:这是多对多表单的核心配置,缺少它的话表单只能选择单个实体,完全无法满足多对多关联的需求,一定要记得加上!choice_label:决定了选项中显示的实体属性,这里用ShopProductImages的file属性来标识每个图片,你也可以根据需求换成其他属性比如name。query_builder:用于过滤可选的实体范围,示例中只筛选id大于1的图片,你可以根据业务逻辑修改查询条件,比如只展示未被关联的图片等。expanded:控制选项的展示样式,设为true会显示为复选框组,false则是下拉多选框,可根据UI需求选择。
实体类多对多映射配置(必做)
光有表单配置还不够,必须先在实体类中完成多对多关联的映射,否则Doctrine无法处理关联数据:
Product实体配置
// src/AppBundle/Entity/Product.php namespace AppBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class Product { // ... 其他属性及构造方法 /** * @ORM\ManyToMany(targetEntity="ShopProductImages", inversedBy="products") * @ORM\JoinTable(name="product_images") // 自定义关联表的表名 */ private $shopProductImages; public function __construct() { $this->shopProductImages = new ArrayCollection(); } // 关联操作方法,表单提交时需要依赖这些方法维护关联 public function getShopProductImages() { return $this->shopProductImages; } public function addShopProductImage(ShopProductImages $image) { if (!$this->shopProductImages->contains($image)) { $this->shopProductImages->add($image); $image->addProduct($this); // 维护反向关联 } } public function removeShopProductImage(ShopProductImages $image) { if ($this->shopProductImages->contains($image)) { $this->shopProductImages->removeElement($image); $image->removeProduct($this); // 维护反向关联 } } }
ShopProductImages实体配置
// src/AppBundle/Entity/ShopProductImages.php namespace AppBundle\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity */ class ShopProductImages { // ... 其他属性及构造方法 /** * @ORM\ManyToMany(targetEntity="Product", mappedBy="shopProductImages") */ private $products; public function __construct() { $this->products = new ArrayCollection(); } // 反向关联的操作方法 public function getProducts() { return $this->products; } public function addProduct(Product $product) { if (!$this->products->contains($product)) { $this->products->add($product); } } public function removeProduct(Product $product) { if ($this->products->contains($product)) { $this->products->removeElement($product); } } }
完成以上配置后,你的表单就能正确处理产品与图片的多对多关联了,提交表单时Doctrine会自动维护关联表product_images中的数据~
内容的提问来源于stack exchange,提问作者Sruj
相关产品推荐
相关产品推荐

