Я слишком долго смотрел на это, и теперь мне нужен другой набор глаз.
Ранее я установил свои отношения между двумя сущностями, Ди 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,
))
Я не уверен, что мне здесь не хватает. Я знаю, что это не должно быть так сложно.