How to Define Relations and Get All Records with Relations in Laravel?

11,766

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:

  1. You can first fetch specific restaurant and then get it's menus via a relationship:

    $restaurant = Restaurant::find(2);
    $menus = $restaurant->menus;
    
  2. 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.

Share:
11,766
Mahdi Alikhani
Author by

Mahdi Alikhani

Updated on June 26, 2022

Comments

  • Mahdi Alikhani
    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 field level 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
      Yasii over 5 years
      in shorthand you can use $restaurant = Restaurants::find(2)->menus;
    • Mahdi Alikhani
      Mahdi Alikhani over 5 years
      still the same..
    • d3jn
      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 with database-design tag.
  • Mahdi Alikhani
    Mahdi Alikhani over 5 years
    I 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
    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
    bl4cksta over 5 years
    As @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
    Mahdi Alikhani over 5 years
    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
    Mahdi Alikhani over 5 years
    i 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
    Mahdi Alikhani over 5 years
    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 !
  • sabbir chowdury
    sabbir chowdury over 5 years
    if 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
    Mahdi Alikhani over 5 years
    thanks 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
    Nabil Farhan over 5 years
    A 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
    sabbir chowdury over 5 years
    That'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
    Mahdi Alikhani over 5 years
    Oh you're right. i think first one is better than the second one.
  • Mahdi Alikhani
    Mahdi Alikhani over 5 years
    Thanks again for helping me.