Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

icey's avatar
Level 23

Trying to make a Recipe app, including Beer

Hey, great minds of the interwebs!   I'm kinda new to Laravel and looking to learn.

I am trying to make a Recipe app in Laravel, that will contain both beer and meal(dinner, desserts, etc..) recipes. But I'm kinda stuck on this concept since Beer recipes are a bit different from meal recipes.

Difference examples

  • A beer recipe has ingredients; though it has hops which is to be added at a spesific times or "steps" in the process.
  • A beer recipe has multiple timings; mash time, boil time, and fermentation time.
  • And more..

I've create a Recipe model and a RecipeController, created the relationship (belongsToMany) between the Ingredients and Recipe (storing the Ingredients in a separate table).

Was hoping to manage all types of recipes from the Recipe model and RecipeController. Because afterall.. It's all recipes.

RecipeController.php

class RecipeController extends Controller
{
    public function index()
    {
       $recipes = Recipe::get();
       
       return view('recipes.index', compact('recipes'));
    }

    public function show(Recipe $recipe)
    {  
        $recipe->with(['ingredients', 'instruction', 'user']);

        return view('recipes.show', compact('recipe'));
    }

    public function create() //create($type = null)
    {
        // am I on the right track here? Or is there a better way?
        //$ingredients = Ingredient::where('type', $type)->get();
        $ingredients = Ingredient::all();

        return view('recipes.create', compact('ingredients'));
    }

}

Recipe.php

class Recipe extends Model
{
    protected $fillable = ['name', 'description', 'image'];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function ingredients()
    {
        return $this->belongsToMany(Ingredient::class, 'recipe_ingredient')
            ->withPivot(['amount', 'measure', 'type', 'time'])
            ->withTimestamps();
    }

    public function instruction()
    {
        return $this->hasOne(Instruction::class);
    }
}

create_recipe_table

public function up()
{
    Schema::create('recipes', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedInteger('user_id');
        $table->string('name')->unique();
        $table->text('description');
        $table->text('image')->nullable();
        $table->timestamps();
    });
}

Ingredient.php

class Ingredient extends Model
{
    protected $fillable = ['name'];

    protected $touches = ['recipe'];

    public function recipe()
    {
        return $this->belongsToMany(Recipe::class, 'recipe_ingredient')
            ->withPivot(['amount', 'measure', 'type', 'time'])
            ->withTimestamps();
    }
}

create_ingredient_table

public function up()
{
    Schema::create('ingredients', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        // more coming.

        $table->timestamps();
    });
}

The Pivot table

public function up()
{
    Schema::create('recipe_ingredient', function (Blueprint $table) {
        $table->increments('id');

        $table->unsignedInteger('recipe_id');
        $table->unsignedInteger('ingredient_id');

        /* This is the extra things I've been thinking */
        $table->float('amount');
        $table->string('measure');
        $table->string('type')->nullable();
        $table->integer('time')->nullable();

        $table->foreign('recipe_id')->references('id')->on('recipes')->onDelete('cascade');
        $table->foreign('ingredient_id')->references('id')->on('ingredients')->onDelete('cascade');

        $table->timestamps();
    });
}

  What would you do? Can I create childmodels for Beer and Meal then use the Recipe model for things in common?   I would like to have all Ingredients in a select-box on my /recipe/create page, and list the ingredients based on what type of recipe I am creating. Best way to define a type element on the Ingredient and do a Ingredient::where('type', $type); ?   Maybe that this is a too big of a starter project. But I'm sticking to it.  And please excuse me if this is not understandable.

Regards icey

0 likes
7 replies
Snapey's avatar

All recipes have a process consisting of multiple steps. Its not sufficient to just have ingredients.

I don't see how beer represents a unique challenge?

icey's avatar
Level 23

@SNAPEY - Thanks for the quick reply! I guess I’ve forgotten to account for the steps in the basic recipe. Would you say that replaces my Instruction class? Didn’t include it in the original post but its just a hasone relationship to the recipe, that consist of a text element.

The challenge with beer, at least in my head. Is that hops is to be added in different times, for example when 15 minutes remain of the boil. At 80 degrees for x-amount of time while cooling down. Or when its 5 days left of the fermentation. Is it correct to assume that the pivot-table should contain this information?

Sorry if I sound like a «please do it for me»-person.

Vilfago's avatar

What about a link like that :

Recipe hasMany Steps which hasMany Ingredients.

You can use hasManyThrough to retrieve ingredients for a recipe.

A beer recipe take longer than a common meal recipe, but I don't see it really different.

A bread, you have to wait for it to raise. A pizza with an egg on top of it, you have to add it during its cooked in the oven.

icey's avatar
Level 23

@VILFAGO - That was my thoughts after @snapeys comment yesterday.

Will test it out later today. And thanks for confirming my theory! Just needed a kick in the brain :-p

mcadio's avatar

@icey How did this go for you? I'm looking to create a blog with recipes using Laravel, and trying to figure out the best place to start.

mcadio's avatar

@seongbae No, I ended up going with Wordpress, which I hate. I'd still love to switch over to Laravel, but don't have the same amount of time as usual.

Please or to participate in this conversation.