skip to Main Content

I have an app where I am trying to store recipes. Now, a recipe will have several details, and I want to be able to save them all at the same time with the parent recipe. My models have the correct relationship declarations.

Recipe table
id, name servings short_description

RecipeDetail table
id, recipe_id, qty, measurement_id, ingredient_id

I’m using Postman to test my API. I’ve tried the following with no success

{ "name": "Homemade Pizza", "recipeDetails": { "qty": 1, "measurement_id": 1, "ingredient_id": 1 },{ "qty": 1, "measurement_id": 2, "ingredient_id": 3 } }

I expect a recipe to be entered into the DB with the name Homemade Pizza and 2 Recipe Details entered into the DB with a recipe_id = to what the newly added recipe id is. Is what I’m trying to do even possible?

Edit

So I’ve done what Karl has suggested below, with the Postman structure

{
    "name": "Zooble Sausage-Pepper Pizza Bites",
    "servings": "2",
    "short_description": "A great dish made in a muffin tin",
    "recipe_details": [
        {
            "qty": 1,
            "measurement_id": 1,
            "ingredient_id": 1
        },
        {
            "qty": 1.5,
            "measurement_id": 2,
            "ingredient_id": 3
        }
    ]
}

Recipe model

public function recipeDetails()
{
    return $this->hasMany(RecipeDetail::class);
}

RecipeDetail model

public function recipe()
{
    return $this->belongsTo(Recipe::class);
}

In my RecipeController, I have the following,

public function store(StoreRecipeRequest $request)
{
    $recipe = $request->user()->recipes()->create($request->validated());
    $recipe_detail_data = $request->input('recipe_details');

    $recipe->recipeDetails()->createMany($recipe_detail_data);

    return RecipeResource::collection(Recipe::with('recipeDetails')->where('id', $recipe->id)->get());
}

The $recipe = $request->user()->recipes()->create($request->validated()); statement works, it is adding the recipe to the db, however when it gets to adding the recipeDetail I’m getting a sql error saying that measurement_id doesn’t have a default value. I’m also wondering about validation of the recipeDetails, is that handled in the first validation or does there need to be a separate validation for the details?

2

Answers


  1. In your Recipe model, ensure you have the recipeDetails relationship defined properly.

    class Recipe extends Model
    {
        // ...
    
        public function recipeDetails()
        {
            return $this->hasMany(RecipeDetail::class);
        }
    }
    

    RecipeDetails model…

    class RecipeDetails extends Model
    {
        // ...
    
        public function recipe()
        {
            return $this->belongsTo(Recipe::class);
        }
    }
    

    Now, in Postman, you need to change your structure slightly.

    {
        "name": "Homemade Pizza",
        "recipe_details": [
            {
                "qty": 1,
                "measurement_id": 1,
                "ingredient_id": 1
            },
            {
                "qty": 1,
                "measurement_id": 2,
                "ingredient_id": 3
            }
        ]
    }
    

    In your controller, you need to do something to the effect of…

    public function store(Request $request)
    {
        $recipeData = $request->only('name');
        $recipe = Recipe::create($recipeData);
    
        $recipeDetailsData = $request->input('recipe_details');
        $recipe->recipeDetails()->createMany($recipeDetailsData);
    
        return response()->json($recipe, 201);
    }
    
    Login or Signup to reply.
  2. it’s not inserting measurement_id in recipe_details table, that’s why you have that error. Check that measurement_id is in $fillables array in RecipeDetails model.
    For validation, $request->input does not check for your custom FormRequest, so its not validated, try having variable like $data = $request->validated();
    and then use $data variable like:

    $recipeDetailData = $data['recipe_details'];
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search