У меня возникают некоторые проблемы при создании формы, в которую входит коллекция другого объекта.
Я хочу создать рецепт, и для этого хочу, чтобы пользователь мог вставить несколько тегов для этого рецепта.
Я следил за текущей документацией по Symfony, и на самом деле я могу вставлять оба объекта Recipe и Tag, но для объекта тега фактически вставлен только идентификатор.
Вот что я сделал до сих пор:
Форма рецепта:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('recipe_tags', CollectionType::class, array(
'entry_type' => TagsType::class,
'allow_add' => true,
'by_reference' => false,
));
}
Что добавляет форму collationType TagsType, которую она кодирует следующим образом:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
}
Затем я создаю объект тега в контроллере заранее, поэтому у объекта рецепта есть тег по умолчанию, который будет обновляться после отправки формы.
$recipe = new Recipe();
$tag = new Tags();
$tag->setName('tag1');
$recipe->addRecipeTag($tag);
$form = $this->get('form.factory')->createNamed(null, RecipeType::class,
$recipe);
И, наконец, Рецепт сущности с (я думаю, так) надлежащей информации:
/**
* @var \Doctrine\Common\Collections\Collection
*
* @ORM\ManyToMany(targetEntity="Tags", inversedBy="idRecipe", cascade=
{"persist"})
* @ORM\JoinTable(name="recipe_tags",
* joinColumns={
* @ORM\JoinColumn(name="id_recipe", referencedColumnName="id_recipe")
* },
* inverseJoinColumns={
* @ORM\JoinColumn(name="id_tag", referencedColumnName="id_tag")
* }
* )
* @Groups({"recipe_detail"})
*
*/
private $recipe_tags;
Я также добавил аннотацию с сохранением каскада, следуя документации. Вот способ добавления тегов.
/**
* Add recipeTag
*
* @param \AppBundle\Entity\Tags $recipeTag
*
* @return Recipe
*/
public function addRecipeTag(\AppBundle\Entity\Tags $recipeTag)
{
$this->recipe_tags[] = $recipeTag;
return $this;
}
И это то, что я вставил в мою базу данных (это возвращение после запроса POST):
{
"recipe": {
"idRecipe": 3671,
"name": "TagName#76232",
"description": null,
"duration": null,
"updatedAt": null,
"createdAt": null,
"active": null,
"image": null,
"portions": null,
"idCategory": null,
"createdBy": null,
"recipeTags": [
{
"idTag": 143,
"name": null
}
],
"recipeSteps": [],
"recipeIngredients": null
}}
Как вы можете видеть, рецепт добавлен в корне, но имя для тега, который я только что создал, не добавляется. Кроме того, сводная таблица recipe_tags не добавляет данные вообще.
Что я делаю не так?
РЕДАКТИРОВАТЬ:
Я думаю, что проблема заключалась в том, что я использовал одно и то же поле имени формы для обоих объектов. Теперь я изменил поле и появилась новая ошибка:
{
"code": 400,
"message": "Validation Failed",
"errors": {
"errors": [
"This value is not valid."
],
"children": {
"name": [],
"recipe_tags": {
"children": [
{
"children": {
"tag": []
}
}
]
}
}
}}
И это параметры, которые я передаю с запросом POST:
{"name":"Recipe#2342"}
{"recipe_tags":"TagName#76232"}
Есть идеи? Спасибо.
Я, наконец, решил проблему. Я не правильно передавал параметры POST. Вот как это должно быть сделано в случае, если форма предназначена для спокойного api:
{
"recipe_form[name]":"recipeName",
"recipe_form[recipe_tags][0][tag]":"tag1",
"recipe_form[recipe_tags][1][tag]":"tag2",
"recipe_form[recipe_tags][2][tag]":"tag3"
}
..и так далее. Я назвал форму, которая помогла мне понять, как это работает. Также нет необходимости создавать теги, а затем передавать их в форму, поэтому я могу создать столько меток, сколько захочу.
Это контроллер:
$recipe = new Recipe();
$form = $this->get('form.factory')->
createNamed('recipe_form', RecipeType::class, $recipe);
$form->handleRequest($request);
if ($form->isValid() && $form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$em->persist($recipe);
$em->flush();
return array("recipe" => $recipe);
}
return array(
'form' => $form,
);
И тогда классы formType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('recipe_tags', CollectionType::class, array(
'entry_type' => TagsType::class,
'allow_add' => true,
'by_reference' => false,
));
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('tag');
}
Приветствия.
С помощью ManyToMany
вы должны просто добавить поле EntityType
только с multiple=true
в RecipeType
и все будет готово, если вы не хотите также создавать новые теги.