Reputation: 100
Here my tables migrations(4):
restaurants:
Schema::create('restaurants', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
foods:
Schema::create('foods', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
ingredients:
Schema::create('ingredients', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
restaurant_has_foods_with_ingredients:
Schema::create('restaurant_has_foods_with_ingredients', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('restaurant_id');
$table->unsignedInteger('food_id');
$table->unsignedInteger('ingredient_id');
$table->foreign('restaurant_id')
->references('id')
->on('restaurants')
->onDelete('cascade');
$table->foreign('food_id')
->references('id')
->on('foods')
->onDelete('cascade');
$table->foreign('ingredient_id')
->references('id')
->on('ingredients')
->onDelete('cascade');
});
How can I define my Restaurant,Food,Ingredient Models with their relations?
Here some examples of my needs:
1-All restaurants with specific ingredient in their serving dishes.
2-All ingredients of a specific dish in a specific restaurant.
3-All dishes with a specific ingredient in a restaurant.
...
-------------------------After Edit-----------------------------
I have my own solution but I think it's not a good one.
Now in my Restaurant model I have two implementation of getting food
One to get all foods of a restaurant:
public function foods()
{
return $this->belongsToMany('App\Models\Food', 'restaurant_has_foods_with_ingredients')
->groupBy('food_id');
}
And another one to get ingredients of current restaurunt's specific food
public function foodIngredients(Food $food)
{
$result = DB::table('restaurant_has_foods_with_ingredients')
->select('restaurant_has_foods_with_ingredients.ingredient_id as ingredient_id')
->where('restaurant_has_foods_with_ingredients.restaurant_id',$this->id)
->where('restaurant_has_foods_with_ingredients.food_id',$food->id)
->get();
$ingredients = array();
foreach ($result as $row) {
$ingredients[] = Ingredient::find($row->ingredient_id);
}
return $ingredients;
}
Upvotes: 2
Views: 281
Reputation: 6269
Basicly its something like this :
Create two migration : restaurant_food
and food_ingredient
we have a
Restaurant model - Food model - ingredient model
A Restaurent can have many types of food and a food can be in served restaurent -> so we have a many to many relation here
Restaurant model
class Restaurant extends Model
{
/**
* The foods that belong to the Restaurant.
*/
public function foods()
{
return $this->belongsToMany('App\Food');
}
}
Alright now with the next thing
1- As we mentioned before , a food type can be served in many restaurants so we need to define the inverse relation.
2- A food has many ingredients and an ingredient can be used in many types of food -> Another many to many
Food model
class Food extends Model
{
/**
* The ingredients that belong to the Food.
*/
public function restaurants()
{
return $this->belongsToMany('App\Restaurant');
}
/**
* The ingredients that belong to the Food.
*/
public function ingredients()
{
return $this->belongsToMany('App\Ingredient');
}
}
Now the same goes for
Ingredient model
class Ingredient extends Model
{
/**
* The foods that belong to the Ingredient.
*/
public function foods()
{
return $this->belongsToMany('App\Food');
}
}
Alright now we have everything setup this is how it's used
Adding to a relation
$Restaurant = Restaurant::find($id);
$Restaurant->foods()->attach($food_id);
Removing from a relation
$Restaurant->foods()->detach($food_id);
1-All restaurants with specific ingredient in their serving dishes.
$restaurants = App\Restaurant::with(['foods' => function ($query) {
$query->whereHas(['ingredients' => function ($query) {
$query->where('name', 'like', 'potato');
}])->get();
2-All ingredients of a specific dish in a specific restaurant.
$ingridients = App\Ingredient::whereHas(['foods' => function ($query) {
$query->where('name', 'like', 'potato')->whereHas(['restaurant' => function ($query) {
$query->where('name', 'like', 'newyork');
}])->get();
3-All dishes with a specific ingredient in a restaurant.
$foods= App\Food::whereHas(['ingredients' => function ($query) {
$query->where('name', 'like', 'potato');
},
'restaurants' => function ($query) {
$query->where('name', 'like', 'newyork');
}
])->get();
change potato/newyork with a variable and you are good to go
My code might have some minor typos or mistakes but i hope you got the idea of how things work
Upvotes: 3