具有多个实体类型的CollectionType + Ajax

时间:2017-03-30 11:26:13

标签: ajax forms symfony doctrine-orm

创建表单时遇到问题,方法是包含一个作为2个相关实体的formType,并且必须与CollectionType结合使用。

我使用库jquery.collection for CollectionType(http://symfony-collection.fuz.org/symfony3/

我的实体

产品

namespace BBW\ProductBundle\Entity\Product;

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;

/**
 * Product
 *
 * @ORM\Table(name="product_product")
 * @ORM\Entity(repositoryClass="BBW\ProductBundle\Repository\Product\ProductRepository")
 */
class Product
{

    use ORMBehaviors\Translatable\Translatable;

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var array
     * @ORM\ManyToMany(targetEntity="BBW\ProductBundle\Entity\Attribute\AttributeGroup", inversedBy="products", fetch="EAGER")
     * @ORM\JoinTable(name="product_join_attribute_group")
     */
    private $attributeGroups;

    /**
     * @var array
     * @ORM\ManyToMany(targetEntity="BBW\ProductBundle\Entity\Attribute\Attribute", inversedBy="products", fetch="EAGER")
     * @ORM\JoinTable(name="product_join_attribute")
     */
    private $attributes;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->attributeGroups = new \Doctrine\Common\Collections\ArrayCollection();
        $this->attributes = new \Doctrine\Common\Collections\ArrayCollection();
    }

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

    /**
     * Add attributeGroup
     *
     * @param \BBW\ProductBundle\Entity\Attribute\AttributeGroup $attributeGroup
     *
     * @return Product
     */
    public function addAttributeGroup(\BBW\ProductBundle\Entity\Attribute\AttributeGroup $attributeGroup)
    {
        $this->attributeGroups[] = $attributeGroup;

        return $this;
    }

    /**
     * Remove attributeGroup
     *
     * @param \BBW\ProductBundle\Entity\Attribute\AttributeGroup $attributeGroup
     */
    public function removeAttributeGroup(\BBW\ProductBundle\Entity\Attribute\AttributeGroup $attributeGroup)
    {
        $this->attributeGroups->removeElement($attributeGroup);
    }

    /**
     * Get attributeGroups
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAttributeGroups()
    {
        return $this->attributeGroups;
    }

    /**
     * Add attribute
     *
     * @param \BBW\ProductBundle\Entity\Attribute\Attribute $attribute
     *
     * @return Product
     */
    public function addAttribute(\BBW\ProductBundle\Entity\Attribute\Attribute $attribute)
    {
        $this->attributes[] = $attribute;

        return $this;
    }

    /**
     * Remove attribute
     *
     * @param \BBW\ProductBundle\Entity\Attribute\Attribute $attribute
     */
    public function removeAttribute(\BBW\ProductBundle\Entity\Attribute\Attribute $attribute)
    {
        $this->attributes->removeElement($attribute);
    }

    /**
     * Get attributes
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAttributes()
    {
        return $this->attributes;
    }
}

AttributeGroup

namespace BBW\ProductBundle\Entity\Attribute;

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;

/**
 * AttributeGroup
 *
 * @ORM\Table(name="product_attribute_group")
 * @ORM\Entity(repositoryClass="BBW\ProductBundle\Repository\Attribute\AttributeGroupRepository")
 */
class AttributeGroup
{
    use ORMBehaviors\Translatable\Translatable;

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var int
     *
     * @ORM\OneToMany(targetEntity="BBW\ProductBundle\Entity\Attribute\Attribute", mappedBy="attributeGroup", cascade={"persist", "remove"}, fetch="EAGER")
     * @ORM\JoinColumn(name="attribute_id")
     */
    private $attributes ;

    /**
     * @var array
     * @ORM\ManyToMany(targetEntity="BBW\ProductBundle\Entity\Product\Product", mappedBy="attributeGroups", cascade={"persist"}, fetch="EAGER")
     */
    private $products;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->attributes = new \Doctrine\Common\Collections\ArrayCollection();
        $this->products = new \Doctrine\Common\Collections\ArrayCollection();
    }

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

    /**
     * Add attribute
     *
     * @param \BBW\ProductBundle\Entity\Attribute\Attribute $attribute
     *
     * @return AttributeGroup
     */
    public function addAttribute(\BBW\ProductBundle\Entity\Attribute\Attribute $attribute)
    {
        $this->attributes[] = $attribute;

        return $this;
    }

    /**
     * Remove attribute
     *
     * @param \BBW\ProductBundle\Entity\Attribute\Attribute $attribute
     */
    public function removeAttribute(\BBW\ProductBundle\Entity\Attribute\Attribute $attribute)
    {
        $this->attributes->removeElement($attribute);
    }

    /**
     * Get attributes
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getAttributes()
    {
        return $this->attributes;
    }


    /**
     * Add product
     *
     * @param \BBW\ProductBundle\Entity\Product\Product $product
     *
     * @return AttributeGroup
     */
    public function addProduct(\BBW\ProductBundle\Entity\Product\Product $product)
    {
        $this->products[] = $product;

        return $this;
    }

    /**
     * Remove product
     *
     * @param \BBW\ProductBundle\Entity\Product\Product $product
     */
    public function removeProduct(\BBW\ProductBundle\Entity\Product\Product $product)
    {
        $this->products->removeElement($product);
    }

    /**
     * Get products
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getProducts()
    {
        return $this->products;
    }
}

属性

namespace BBW\ProductBundle\Entity\Attribute;

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;

/**
 * Attribute
 *
 * @ORM\Table(name="product_attribute")
 * @ORM\Entity(repositoryClass="BBW\ProductBundle\Repository\Attribute\AttributeRepository")
 */
class Attribute
{
    use ORMBehaviors\Translatable\Translatable;

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var int
     *
     * @ORM\ManyToOne(targetEntity="BBW\ProductBundle\Entity\Attribute\AttributeGroup", inversedBy="attributes", cascade={"persist"}, fetch="EAGER")
     * @ORM\JoinColumn(name="attribute_group_id")
     */
    private $attributeGroup ;

    /**
     * @var array
     * @ORM\ManyToMany(targetEntity="BBW\ProductBundle\Entity\Product\Product", mappedBy="attributes", cascade={"persist"}, fetch="EAGER")
     */
    private $products;

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

    /**
     * Set attributeGroup
     *
     * @param \BBW\ProductBundle\Entity\Attribute\AttributeGroup $attributeGroup
     *
     * @return Attribute
     */
    public function setAttributeGroup(\BBW\ProductBundle\Entity\Attribute\AttributeGroup $attributeGroup = null)
    {
        $this->attributeGroup = $attributeGroup;

        return $this;
    }

    /**
     * Get attributeGroup
     *
     * @return \BBW\ProductBundle\Entity\Attribute\AttributeGroup
     */
    public function getAttributeGroup()
    {
        return $this->attributeGroup;
    }

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->products = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Add product
     *
     * @param \BBW\ProductBundle\Entity\Product\Product $product
     *
     * @return Attribute
     */
    public function addProduct(\BBW\ProductBundle\Entity\Product\Product $product)
    {
        $this->products[] = $product;

        return $this;
    }

    /**
     * Remove product
     *
     * @param \BBW\ProductBundle\Entity\Product\Product $product
     */
    public function removeProduct(\BBW\ProductBundle\Entity\Product\Product $product)
    {
        $this->products->removeElement($product);
    }

    /**
     * Get products
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getProducts()
    {
        return $this->products;
    }
}

解释

我的产品必须属于属性组,并且必须包含属性。我的AttributeGroup实体和属性关系之间存在关系。

My Entity AttributeGroup与Attribute(functional)有关系。

表单类型

在我的表单中,我有一个CollectionType,另一个formType作为entry_type,我创建了两个实体类型(AttributeGroups / Attributes)

产品的FormType

namespace BBW\ProductBundle\Form\Product;

use A2lix\TranslationFormBundle\Form\Type\TranslationsType;
use BBW\CoreBundle\FormTypes\SwitchType;
use BBW\MediaBundle\Transformers\MediaTransformer;
use BBW\ProductBundle\Form\Attribute\Type\AttributeType;
use Doctrine\ORM\Mapping\Entity;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\MoneyType;
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 ProductEditType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $locale = $options['int_service'];

        $builder
            ->add('attributes', CollectionType::class, array(
                'entry_type' => AttributeType::class,
                'entry_options' => array(
                    'label' => false
                ),
                'allow_add' => true,
                'allow_delete' => true,
                'prototype' => true,
                'required' => false,
                'attr' => array(
                    'class' => 'attributes-selector'
                ),
            ))
            ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'BBW\ProductBundle\Entity\Product\Product',
            'int_service' => ['fr'],
            'translation_domain' => 'ProductBundle'
        ));
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'bbw_productbundle_edit_product';
    }
}

属性类型

/**
 * Form Type: Fields add in product edit form
 */

namespace BBW\ProductBundle\Form\Attribute\Type;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class AttributeType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('attributeGroups', EntityType::class, array(
                'label' => false,
                'class' => 'BBW\ProductBundle\Entity\Attribute\AttributeGroup',
                'choice_label' => 'translate.name',
                'attr' => array(
                    'class' => 'choiceAttributeGroup'
                ),
            ))
            ->add('attributes', EntityType::class, array(
                'label' => false,
                'class' => 'BBW\ProductBundle\Entity\Attribute\Attribute',
                'choice_label' => 'translate.name',
                'attr' => array(
                    'class' => 'choiceAttributes'
                )
            ))
        ;
    }

    /**
     * {@inheritdoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'BBW\ProductBundle\Entity\Product\Product',
            'int_service' => ['fr'],
            'translation_domain' => 'ProductBundle'
        ));
    }

}

解释

两个实体(AttributeGroups / Attributes)是两个链接的下拉列表。当我选择一个组时,我必须在第二个下拉列表中显示该组的数据。这部分效果很好。我可以根据需要复制(使用CollectionType)。

提交表单时

第一个问题

"无法确定属性"属性组"的访问类型"

当我设置" mapped =>时,

第二个问题假"在我的两个实体中:

"类型" Doctrine \ Common \ Collections \ Collection | array"的预期值对于关联字段" BBW \ ProductBundle \ Entity \ Product \ Product#$ attributes",得到" BBW \ ProductBundle \ Entity \ Product \ Product"代替"

Screeshoots dump / form

Screen for my collection type with two related dropdown Screen for my dump when i submit

结论

我认为我的问题是一个映射问题,在symfony doc或其他网站上测试了很多代码和解释,我无法解决我的问题。如果有人可以帮我解释一下具有2个实体的collectionType的好工作,如果可能的话。如果你有代码的例子我也是接受者。

提前感谢您的帮助。

0 个答案:

没有答案