Symfony CollectionType отношение многих ко многим в форме редактирования - PullRequest
1 голос
/ 05 июня 2019

У меня с 3-мя сущностями. Meal, Product и ProductsQuantity. Между Meal и ProductQuantity есть отношение многих ко многим. Добавление данных работает нормально, все данные сохраняются в сущности, но проблема в том, когда вы хотите редактировать форму. Тогда я получил ошибку:

Предполагается, что данные представления формы являются экземпляром класса MealBundle\Entity\ProductsQuantity, но являются экземпляром класса Doctrine\ORM\PersistentCollection. Вы можете избежать этой ошибки, установив для параметра "data_class" значение null или добавив преобразователь представления, который преобразует экземпляр класса Doctrine\ORM\PersistentCollection в экземпляр MealBundle\Entity\ProductsQuantity.

Я пытался с опцией data_class установить null и установить fetch="EAGER" для отношения, но это не решило проблему.

Питание:

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

/**
 * @var string
 * @ORM\Column(name="name", type="string", length=255)
 */
protected $name = "";

/**
 * @var ProductsQuantity[]|Collection
 * @ORM\ManyToMany(targetEntity="ProductsQuantity", inversedBy="meal", cascade={"persist"}, fetch="EAGER")
 * @ORM\JoinTable(name="meal_products_quantity_relations",
 *     joinColumns={@ORM\JoinColumn(name="meal_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="products_quantity_id", referencedColumnName="id")}
 * )
 */
protected $productsQuantity;


/**
 * Meal constructor.
 */
public function __construct()
{
    $this->productsQuantity = new ArrayCollection();
}

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

/**
 * @param int $id
 * @return Meal
 */
public function setId(int $id): Meal
{
    $this->id = $id;
    return $this;
}

/**
 * @return string
 */
public function getName(): string
{
    return $this->name;
}

/**
 * @param string $name
 * @return Meal
 */
public function setName(string $name): Meal
{
    $this->name = $name;
    return $this;
}

/**
 * @return Collection|ProductsQuantity[]
 */
public function getProductsQuantity()
{
    return $this->productsQuantity;
}

/**
 * @param Collection|ProductsQuantity[] $productsQuantity
 * @return Meal
 */
public function setProductsQuantity($productsQuantity)
{
    $this->productsQuantity = $productsQuantity;
    return $this;
}

ProductQuantity:

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

/**
 * @var Product
 * @ORM\JoinColumn(name="product_id", referencedColumnName="id")
 * @ORM\ManyToOne(targetEntity="Product", inversedBy="productsQuantity")
 */
protected $product;

/**
 * @var integer
 * @ORM\Column(name="amount", type="integer")
 */
protected $amount;

/**
 * @var $meal
 * @ORM\ManyToMany(targetEntity="MealBundle\Entity\Meal", mappedBy="productsQuantity")
 */
protected $meal;


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

/**
 * @param mixed $id
 * @return ProductsQuantity
 */
public function setId($id)
{
    $this->id = $id;
    return $this;
}

/**
 * @return Product
 */
public function getProduct(): ?Product
{
    return $this->product;
}

/**
 * @param Product $product
 * @return ProductsQuantity
 */
public function setProduct(Product $product): ProductsQuantity
{
    $this->product = $product;
    return $this;
}

/**
 * @return int
 */
public function getAmount(): ?int
{
    return $this->amount;
}

/**
 * @param int $amount
 */
public function setAmount(int $amount): void
{
    $this->amount = $amount;
}

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

/**
 * @param mixed $meal
 * @return ProductsQuantity
 */
public function setMeal($meal)
{
    $this->meal = $meal;
    return $this;
}

Форма питания:

class MealType extends AbstractType
{
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options = [])
{
    parent::buildForm($builder, $options);

    /** @var Meal $meal */
    $meal = $options['data'];
    $data = null;

    if(!empty($meal)) {
        $data = $meal->getProductsQuantity();
    } else {
        $data = new ProductsQuantity();
    }

    $builder
        ->add('name', TextType::class,[
            'label' => 'Nazwa Dania',
            'required' => true
        ])->add('productsQuantity', CollectionType::class, [
            'data_class' => null,
            'label' => 'Produkty',
            'entry_type' => ProductsQuantityType::class,
            'allow_add' => true,
            'data' => ['productsQuantity' => $data],
            'prototype_name' => '__product__',
            'entry_options' => [
                'allow_extra_fields' => true,
                'label' => false
            ],
            'prototype' => true
        ])->add('addProduct', ButtonType::class, [
            'label' => 'Dodaj kolejny produkt',
            'attr'  => [
                'class' => 'btn-default addProductEntry'
            ]
        ])->add('submit', SubmitType::class, [
            'label' => 'Dodaj'
        ]);
}

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

ПродукцияКоличество форм:

class ProductsQuantityType extends AbstractType
{
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    parent::buildForm($builder, $options);

    $builder
        ->add('product', EntityType::class,[
            'class' => Product::class,
            'label' => 'Nazwa produktu',

        ])
        ->add('amount', NumberType::class, [
            'label' => 'Ilość',
            'required' => true,
            'attr' => [
                'placeholder' => 'ilość'
            ]
        ])
        ->add('removeProduct', ButtonType::class, [
            'label' => 'X',
            'attr'  => [
                'class' => 'btn-danger removeProductEntry'
            ]
        ]);
}

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

Если я изменю 'data' => ['productsQuantity' => $data] на 'data' => ['productsQuantity' => new ProductsQuantity()], ошибки не будет, но есть пустая ProductsQuantity часть формы MealType. Может кто-нибудь сказать мне, как это исправить?

...