symfony отправка в таблицу ссылок - PullRequest
0 голосов
/ 20 апреля 2020

Я слишком долго смотрел на это, и теперь мне нужен другой набор глаз.

Ранее я установил свои отношения между двумя сущностями, Ди sh и Ингредиентом, как многие ко многим отношения, и форма ассоциации работает отлично. Однако впоследствии я понял, что мне нужно другое поле в моей таблице ссылок, чтобы указать «количество», поэтому в результате я создал новую сущность DishIngredient. Он создал ту же таблицу, но вместо многих ко многим, теперь это одна таблица с двумя отношениями «многие к одному» с Di sh и Ingredient.

Пока все хорошо. У меня все работает, пока я не попытаюсь связать ингредиенты с блюдами. Я могу успешно сгенерировать форму для отображения каждого из ингредиентов, однако при отправке я сталкиваюсь с проблемами. Он пытается отправить в Ingredient вместо DishIngredient.

Вот что у меня есть:

Мой контроллер:

/**
 * @Route("/recipe/ingredient/{id}", name="edit_ingredients")
 */
public function ingredientEdit(Request $request, Dish $dish, $id)
{
    $user = $this->getUser();

    $dish_id = $dish->getId();
    $dish = $this->getDoctrine()->getRepository(Dish::class)->findOneBy(array('id' =>$dish_id ));

    $dish_user = $dish->getUser();
    //in case someone tries to manually hack into someone else's recipe
    if($dish_user != $user) {
        return $this->render('dishes/error.html.twig', array(
                'dish' => $dish,
                'user' => $user
            )
        );

    }
    else {
        $form = $this->createForm(IngredientType::class, $dish);

        $form->handleRequest($request);

        if($form->isSubmitted() && $form->isValid()) {
            $dish = $form->getData();
            $em = $this->getDoctrine()->getManager();

            $em->persist($dish);
            $em->flush();

            return $this->redirectToRoute('edit_ingredients', array('id' => $id));

        }
        return $this->render('dishes/ingredients.html.twig', array(
                'form' => $form->createView(),
                'dish' => $dish
            )
        );

    }
}

Который затем загружает эту форму:

class IngredientType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options); // TODO: Change the autogenerated stub

        $ingredient = new Ingredient();

        $builder
            ->add('DishIngredients',EntityType::class, array(
                'required' => false,
                'attr' => array('class' => 'form-control'),
                'class' => Ingredient::class,
                'query_builder' => function(IngredientRepository $ir) {
                    return $ir->createQueryBuilder('s')
                        ->orderBy('s.name', 'ASC');
                },
                'multiple' => true,
                'expanded' => true,
            ))


            ->add('save', SubmitType::class, array(
                'label' => 'Update',
                'attr' => array('class' => 'btn btn-primary mt-3')
            ))
            ->getForm();

    }

}

На ветке отображается нормально:

{{ form_start(form) }}
    {% for i in form.DishIngredients %}
    {{ form_widget(i) }} {{ form_label(i) }}<br>
     {% endfor %}
{{ form_end(form) }}

Однако проблема в том, что, когда я пытаюсь отправить его, я получаю эту ошибку:

Ожидаемое значение типа «App \ Entity \ DishIngredient» для поля ассоциации «App \ Entity \ Dish # $ dishIngredients», вместо этого получено «App \ Entity \ Ingredient».

Если я изменю форма для вызова DishIngredient вместо Ingredient, она не показывает ни одного ингредиента; он просто создает текстовое поле для поиска ввода; не то, что я хочу или нужно вообще.

Вот сущность DishIngredient:

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="App\Repository\DishIngredientRepository")
 */
class DishIngredient
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Dish", inversedBy="dishIngredients")
     */
    private $dish;

    /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Ingredient", inversedBy="dishIngredients")
     */
    private $ingredient;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $amount;

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

    public function getDish(): ?Dish
    {
        return $this->dish;
    }

    public function setDish(?Dish $dish): self
    {
        $this->dish = $dish;

        return $this;
    }

    public function getIngredient(): ?Ingredient
    {
        return $this->ingredient;
    }

    public function setIngredient(?Ingredient $ingredient): self
    {
        $this->ingredient = $ingredient;

        return $this;
    }

    public function getAmount(): ?string
    {
        return $this->amount;
    }

    public function setAmount(?string $amount): self
    {
        $this->amount = $amount;

        return $this;
    }
}

и вот сущность Ingredient для справки

/**
 * @ORM\Entity(repositoryClass="App\Repository\IngredientRepository")
 */
class Ingredient
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

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

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\DishIngredient", mappedBy="ingredient")
     */
    private $dishIngredients;


    public function __toString(): ?string
    {
        // TODO: Implement __toString() method.
        return $this->name;
    }

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

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

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

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }


/**
 * @return Collection|DishIngredient[]
 */
public function getDishIngredients(): Collection
{
    return $this->dishIngredients;
}

public function addDishIngredient(DishIngredient $dishIngredient): self
{
    if (!$this->dishIngredients->contains($dishIngredient)) {
        $this->dishIngredients[] = $dishIngredient;
        $dishIngredient->setIngredient($this);
    }

    return $this;
}

public function removeDishIngredient(DishIngredient $dishIngredient): self
{
    if ($this->dishIngredients->contains($dishIngredient)) {
        $this->dishIngredients->removeElement($dishIngredient);
        // set the owning side to null (unless already changed)
        if ($dishIngredient->getIngredient() === $this) {
            $dishIngredient->setIngredient(null);
        }
    }

    return $this;
}}

У кого-нибудь есть здесь идеи?

- РЕДАКТИРОВАТЬ:

Хорошо, поэтому я создал новую форму с именем DishIngredientType и переместил в нее информацию сверху, а затем изменил IngredientType, чтобы вместо него было следующее:

    $builder
        ->add('DishIngredients',CollectionType::class, array(
            'required' => false,
            'attr' => array('class' => 'form-control'),
            'entry_type' => DishIngredientType::class,
            'entry_options' => ['label' => false],

        ))

, но теперь я ' Я только получаю текстовое поле плана (без параметров).

Вот как они выглядят в DishIngredientType

        ->add('DishIngredients',EntityType::class, array(
            'required' => false,
            'attr' => array('class' => 'form-control'),
            'class' => Ingredient::class,
            'query_builder' => function(IngredientRepository $ir) {
                return $ir->createQueryBuilder('s')
                    ->orderBy('s.name', 'ASC');
            },
            'multiple' => true,
            'expanded' => true,
        ))

Я не уверен, что мне здесь не хватает. Я знаю, что это не должно быть так сложно.

...