【问题标题】:Symfony - form - many to many relation - collection typeSymfony - 形式 - 多对多关系 - 集合类型
【发布时间】:2016-09-28 15:13:22
【问题描述】:

情况如下:

我有一个实体属性

class Property
{
    /**
     * @ORM\Id
     * @ORM\Column(type="string")
     * @ORM\GeneratedValue(strategy="UUID")
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="PropertyEquipment", inversedBy="properties")
     */
    protected $propertyEquipments;

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

    public function getId()
    {
        return $this->id;
    }

    public function addPropertyEquipment(\AppBundle\Entity\PropertyEquipment $propertyEquipment)
    {
        $this->propertyEquipments[] = $propertyEquipment;

        return $this;
    }

    public function removePropertyEquipment(\AppBundle\Entity\PropertyEquipment $propertyEquipment)
    {
        $this->propertyEquipments->removeElement($propertyEquipment);
    }

    public function getPropertyEquipments()
    {
        return $this->propertyEquipments;
    }
}

以及实体PropertyEquipment:

class PropertyEquipment
{

    /**
     * @ORM\Id
     * @ORM\Column(type="string")
     * @ORM\GeneratedValue(strategy="UUID")
     */
    protected $id;

    /**
     * @ORM\ManyToMany(targetEntity="Property", mappedBy="propertyEquipments")
     */
    protected $properties;

    /**
     * @ORM\Column(type="string", length=100)
     * @Gedmo\Translatable
     */
    protected $equipmentName;


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

    /**
     * Get id
     *
     * @return string
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * @return mixed
     */
    public function getEquipmentName()
    {
        return $this->equipmentName;
    }

    /**
     * @param mixed $equipmentName
     */
    public function setEquipmentName($equipmentName)
    {
        $this->equipmentName = $equipmentName;
    }

    public function addProperty(Property $property)
    {
        $this->properties[] = $property;

        return $this;
    }

    public function removeProperty(Property $property)
    {
        $this->properties->removeElement($property);
    }

    public function getProperties()
    {
        return $this->properties;
    }
}

PropertyCreation 表单

class PropertyCreation extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            //with this I see the values coming from DB in the template
            ->add("propertyEquipments", PropertyEquipmentCreation::class)

            //with this it's empty :/
            /*->add("propertyEquipments", CollectionType::class, array(
                "entry_type" => PropertyEquipmentCreation::class,
            ))*/
    }

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

这里是 PropertyEquipmentCreation 的形式:

class PropertyEquipmentCreation extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder      
            ->add('propertyEquipment', EntityType::class, [
                'class' => 'AppBundle\Entity\PropertyEquipment',
                'choice_label' => 'equipmentName',
                'expanded' => true,
                'multiple' => true
            ]);
    }

    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => PropertyEquipment::class,
        ]);
    }
}

还有控制器

public function createPropertyAction(Request $request)
{
    $property = new Property();

    $form = $this->createForm(PropertyCreation::class, $property);
    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($property);
        $entityManager->flush();

        return $this->redirectToRoute('homepage');
    }
    return $this->render('form/owner_create_property.html.twig', ["form" => $form->createView()]);
}

我的错误:

Expected value of type "Doctrine\Common\Collections\Collection|array" for association field "AppBundle\Entity\Property#$propertyEquipments", got "Doctrine\Common\Collections\ArrayCollection" instead.

我必须用class PropertyEquipmentTransformer implements DataTransformerInterface 之类的东西来转换这些吗?

【问题讨论】:

  • 没有CollectionType 你是如何处理视图的?您如何将字段存储在 data-prototype 中?

标签: php doctrine-orm many-to-many symfony


【解决方案1】:

我认为您应该在PropertyEquipmentCreation 中使用getParent() 函数并从EntityType::class 继承,然后将所有字段配置放入configureOptions() 函数中(删除buildForm 函数),它应该可以工作。

您遇到这个问题是因为它在您的实现中是 compound form 而不是 simple form 并且 symfony 无法解析在子表单中创建的哪个字段需要用作实体字段的源

【讨论】:

    【解决方案2】:

    首先!

    非常感谢尼克劳斯!

    这里是解决方案(PropertyEquipmentCreation):

    namespace AppBundle\Form\Type;
    
    use Symfony\Bridge\Doctrine\Form\Type\EntityType;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    
    
    class PropertyEquipmentCreation extends AbstractType
    {
    
    /**
     * @param OptionsResolver $resolver
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'class' => 'AppBundle\Entity\PropertyEquipment',
            'choice_label' => 'equipmentName',
            'expanded' => true,
            'multiple' => true,
        ]);
    }
    
    public function getParent()
    {
        return EntityType::class;
    }
    }
    

    对于 (PropertyCreation)

    <?php
    
    
    namespace AppBundle\Form;
    
    
    use AppBundle\Form\Type\PropertyEquipmentCreation;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\Extension\Core\Type\SubmitType;
    use Symfony\Component\Form\Extension\Core\Type\TextareaType;
    use Symfony\Component\Form\Extension\Core\Type\TextType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    
    class PropertyCreation extends AbstractType
    {
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('description', TextareaType::class)
            ->add('name', TextType::class)
            ->add("propertyEquipments", PropertyEquipmentCreation::class)
            ->add('save', SubmitType::class);
    }
    
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => Property::class
        ));
    }
    }
    

    非常感谢!

    【讨论】:

      【解决方案3】:

      尝试使用 Doctrine ArrayCollection 而不是 ArrayCollections:

      $this->propertyEquipments = new \Doctrine\Common\Collections\ArrayCollection();
      

      这应该可行!

      【讨论】:

      • 嗨曼努埃尔 :) 我会试试 :)
      • 嗨 Manuel,这就是我使用的...使用 Doctrine\Common\Collections\ArrayCollection;关联字段“AppBundle\Entity\Property#$propertyEquipments”的“Doctrine\Common\Collections\Collection|array”类型的预期值改为“Doctrine\Common\Collections\ArrayCollection”。但是谢谢 :)
      • 嗯您正在导入它,但我认为您没有在构造函数中使用,您是否替换了 new ArrayCollection();到新的 \Doctrine\Common\Collections\ArrayCollection(); ?
      • 我找到了解决方案...我会在几分钟后发布:)
      猜你喜欢
      • 2020-03-02
      • 1970-01-01
      • 2022-01-22
      • 2012-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多