Symfony 3.4 - Doctrine ManyToMany association error

Clash Royale CLAN TAG#URR8PPP
Symfony 3.4 - Doctrine ManyToMany association error
I'm working on a simple Symfony API and I'm having trouble setting a relation between two entities.
I have this two classes: Recipe and Ingredient.
A Recipe can have many ingredients and an ingredient can be present in many recipes so I used a ManyToMany association.
This is my Recipe class:
namespace RecipesBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
/**
* Recipe
*
* @ORMTable(name="recipe")
* @ORMEntity(repositoryClass="RecipesBundleRepositoryRecipeRepository")
*/
class Recipe
/**
* @var int
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORMColumn(name="name", type="string", length=255)
*/
private $name;
/**
* @var string
*
* @ORMColumn(name="description", type="string", length=255, nullable=true)
*/
private $description;
/**
* @var string
*
* @ORMColumn(name="image", type="string", length=255, nullable=true)
*/
private $image;
/**
* @ORMManyToMany(targetEntity="Ingredient", inversedBy="recipes")
* @ORMJoinTable(name="recipes_ingredients")
*/
private $ingredients;
public function __construct()
$this->ingredients = new ArrayCollection();
/**
* Get id
*
* @return int
*/
public function getId()
return $this->id;
/**
* Set name
*
* @param string $name
*
* @return Recipe
*/
public function setName($name)
$this->name = $name;
return $this;
/**
* Get name
*
* @return string
*/
public function getName()
return $this->name;
/**
* Set description
*
* @param string $description
*
* @return Recipe
*/
public function setDescription($description)
$this->description = $description;
return $this;
/**
* Get description
*
* @return string
*/
public function getDescription()
return $this->description;
/**
* Set image
*
* @param string $image
*
* @return Recipe
*/
public function setImage($image)
$this->image = $image;
return $this;
/**
* Get image
*
* @return string
*/
public function getImage()
return $this->image;
/**
* Set ingredients
*
* @param array $ingredients
* @return Recipe
*/
public function setIngredients($ingredients)
foreach($ingredients as $ingredient)
$this->ingredients->add($ingredient);
return $this;
/**
* Get ingredients
*
* @return ArrayCollection
*/
public function getIngredients()
return $this->ingredients;
This is my Ingredient class:
namespace RecipesBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
/**
* Ingredient
*
* @ORMTable(name="ingredient")
*
@ORMEntity(repositoryClass="RecipesBundleRepositoryIngredientRepository")
*/
class Ingredient
/**
* @var int
*
* @ORMColumn(name="id", type="integer")
* @ORMId
* @ORMGeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORMColumn(name="name", type="string", length=255)
*/
private $name;
/**
* @var int
*
* @ORMColumn(name="amount", type="integer")
*/
private $amount;
/**
* @ORMManyToMany(targetEntity="Recipe", mappedBy="ingredients")
*/
private $recipes;
public __construct()
$this->recipes = new ArrayCollection();
/**
* Get id
*
* @return int
*/
public function getId()
return $this->id;
/**
* Set name
*
* @param string $name
*
* @return Ingredient
*/
public function setName($name)
$this->name = $name;
return $this;
/**
* Get name
*
* @return string
*/
public function getName()
return $this->name;
/**
* Set amount
*
* @param integer $amount
*
* @return Ingredient
*/
public function setAmount($amount)
$this->amount = $amount;
return $this;
/**
* Get amount
*
* @return int
*/
public function getAmount()
return $this->amount;
And this is my controller:
class RecipeController extends Controller
/**
* @Route("/recipes")
*/
public function recipesAction(Request $request)
switch($request->getMethod())
case 'GET':
$recipes = $this->getDoctrine()->getRepository(Recipe::class)->findAll();
$return = $recipes;
break;
case 'POST':
$recipe = new Recipe();
$recipeData = json_decode($request->getContent(), true);
$recipe->setName($recipeData['name']);
$recipe->setDescription($recipeData['description']);
$recipe->setImage($recipeData['imagePath']);
$ingredients = $recipeData['ingredients'];
//var_dump($ingredients);die;
$recipe->setIngredients($ingredients);
//var_dump($recipe);die;
$em = $this->getDoctrine()->getManager();
$em->persist($recipe);
$em->flush();
$return = 'Recipe saved successfully';
break;
case 'PUT':
$recipes = json_decode($request->getContent(), true);
$em = $this->getDoctrine()->getManager();
foreach($recipes as $updating_recipe)
$recipe = $this->getDoctrine()->getRepository(Recipe::class)->findOneBy(array('name' => $updating_recipe['name']));
if($recipe)
$recipe->setName($updating_recipe['name']);
$recipe->setDescription($updating_recipe['description']);
$recipe->setImage($updating_recipe['image']);
$recipe->setIngredients($updating_recipe['ingredients']);
$em->flush();
$return = 'Recipes saved successfully';
break;
case 'DELETE':
break;
return new JsonResponse($return);
The problem occurs when I try to save a new recipe (post request).
I get the following error:
Expected value of type "DoctrineCommonCollectionsCollection|array" for association field "RecipesBundleEntityRecipe#$ingredients", got "array" instead.
I don't understand why I get this error if I use the setIngredients correctly to add the ingredients to the array collection.
Any ideas on what could be wrong?
Thanks in advance
EDIT 1:
I'm adding the dump of the ingredients as requested:
array (size=1)
0 =>
array (size=2)
'name' => string 'Spaghetti' (length=9)
'amount' => int 10
1 Answer
1
Ok the problem is solved.
As Sami indicated, I had to iterate through the ingredients that come
in the request and create an Ingredient object for each one.
Then add them to an ArrayCollection and set it using $recipe->setIngredients();
Thank you very much for your help.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
please post the date your are sending when callin the API, or post the result of //var_dump($ingredients). I thing the problem is here : $ingredients = $recipeData['ingredients']; Perhaps you sould make a loop, create an new ingredient object, hydrate it, push it in a arrat an then pass this array as an argument to setIngredients()
– Sami
Aug 10 at 19:26