How to Define Relations and Get All Records with Relations in Laravel?
Solution 1
IN user model
public function restaurant(){
return $this->hasMany(Restaurant::class,'user_id','id');
}
Restaurant model
public function menus(){
return $this->hasMany(Menu::class,'id','menu_id');
}
Menu model
public function restaurants(){
return $this->belongsTo(Restaurant::class);
}
As you aspect your output you need to write
$result = Restaurant::with('menus')->where('id',2)->get();
you will get relational data. Like which restaurants has which menus.
You also can use this for your scenario. Use this in your Restaurant model
public function menues(){
return $this>hasManyThrough(Menu::class,restaurant_menu::class,'menu_id','id','id','restaurant_id');
}
Solution 2
Relations you define are not available for you in the query scope of your builder instance the way you tried to call them. They are available in the context of your models. Including your relationships in the queries is done differently - you should check official documentation on the matter first.
In your case, if you want to select all menus that belong to specific restaurant you have to ways:
-
You can first fetch specific restaurant and then get it's menus via a relationship:
$restaurant = Restaurant::find(2); $menus = $restaurant->menus;
-
You can query for menus via
Menu
model:$menus = Menu::whereHas('restaurants', function ($query) { $query->where('id', 2); })-get();
Also your relations are set up wrong. Based on table structure you've provided your menus and restaurants are in many-to-many relationship. Therefore restaurants()
relation method in Menu
class needs to return BelongsToMany
instance. So while you're at it I would strongly suggest for you to go over relationships documentation and watch examples until you get the concepts of how different relationships work in Laravel.
Mahdi Alikhani
Updated on June 26, 2022Comments
-
Mahdi Alikhani almost 2 years
I want to define a relationship between tables, and I don't know where I'm going wrong.
These are my tables:
users
-id -email -level
restaurants
-id -name -user_id
menus
-id -name
restaurant_menu
-restaurant_id -menu_id -price
In the
users
table, the fieldlevel
will set by me with two words:[user]
or[restaurant]
.User Model
public function restaurant(){ return $this->hasOne(Restaurant::class); }
Restaurant Model
public function menus(){ return $this->hasMany(Menu::class); }
Menu Model
public function restaurants(){ return $this->belongsTo(Restaurant::class); }
I expect the output of this code:
$result = $restaurant->where('id',2)->menus()->get();
To be records and relations, but i get the following error.
BadMethodCallException Call to undefined method Illuminate\Database\Eloquent\Builder::menus()
What should I do?
-
Yasii over 5 yearsin shorthand you can use
$restaurant = Restaurants::find(2)->menus;
-
Mahdi Alikhani over 5 yearsstill the same..
-
d3jn over 5 years@MahdiAlikhani that's because your relationships are set up incorrectly. You should use
belongsToMany
relationship for your Restaurant-vs-Menu relation as I stated in my answer. If you are struggling with creating a proper table structure for you problem, create a separate question withdatabase-design
tag.
-
-
Mahdi Alikhani over 5 yearsI wrote this code with echo and return and get this error :
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string
, but without return and echo i didn't get error but it shows me nothing. -
twigg over 5 years@MahdiAlikhani that’s just a very simple generic PHP error that’s nothing to do with Laravel. As the error says you can’t covert an object to a string, if you just want to see the contents of the object then var_dump() is what you need or even better laravels dd() function so you have formatting as well
-
bl4cksta over 5 yearsAs @twigg mentioned, this is a generic PHP error. You have to run with for loop on it. Or you can get a dump via dd function of Laravel.
dd($restaurant->menus());
-
Mahdi Alikhani over 5 yearsyou know , in this scenario, i have menus table that i'm keeping menus in it, and restaurant_menu for pivot table to keep each restaurant menus and prices in it, i'm confused and don't know what to do !
-
Mahdi Alikhani over 5 yearsi did all of this, but i have to create restaurant_id field in menus table, i think this won't help me, you know , in this scenario, i have menus table that i'm keeping menus in it, and restaurant_menu for pivot table to keep each restaurant menus and prices in it, i'm confused and don't know what to do !
-
Mahdi Alikhani over 5 yearsyou know , in this scenario, i have menus table that i'm keeping menus in it, and restaurant_menu for pivot table to keep each restaurant menus and prices in it, i'm confused and don't know what to do !
-
sabbir chowdury over 5 yearsif you want to do like what you say then you need to use "hasManyThrough" relation in your model.as I edit my answer. You will find the new suggestion in last function
-
Mahdi Alikhani over 5 yearsthanks for your answer, i used your code and change some of it and finally get the result ! i have one more question, how can i store $request data in Restaurant_Menu table ? i have a panel for restaurant owners that they will create their own menus from the list and set prices, all of this information have to store in *Restaurant_Menu table.
-
Nabil Farhan over 5 yearsA restaurant may have more than one menu. But is the reverse true? Can a menu be applicable for more than one restaurant? If yes, then you need a pivot table. Otherwise you should only use 'restaurant_id' in menus table.
-
sabbir chowdury over 5 yearsThat's totally depends on you. How you maintain your font end design. You can easily use drop down selectors that give one user to select restaurant_id and menu_id a a text field to set prices. Other way you can select your restaurant and then just pic menu id and set price. But remember one thing if you using 2nd idea then you need to pass restaurant id in a hidden filed. Hope you understand
-
Mahdi Alikhani over 5 yearsOh you're right. i think first one is better than the second one.
-
Mahdi Alikhani over 5 yearsThanks again for helping me.