eloquent filter result based on foreign table attribute

6.1k Views Asked by At

I'm using laravel and eloquent.
Actually I have problems filtering results from a table based on conditions on another table's attributes.
I have 3 tables:

  • venue
  • city


    here are the relationships:
    a city has many locations and a location belongs to a city.
    a location belongs to a venue and a venue has one location.

I have a city_id attribute on locations table, which you may figured out from relationships.

The question is simple:
how can I get those venues which belong to a specific city?
the eloquent query I expect looks like this:
$venues=Venue::with('location')->where('location.city_id',$city->getKey());

Of course that's not gonna work, but seems like this is common task and there would be an eloquent command for it.
Thanks!

2

There are 2 best solutions below

4
EricMakesStuff On BEST ANSWER

A couple of options:

$venues = Venue::whereIn('location_id', Location::whereCityId($city->id)->get->lists('id'))
    ->get();

Or possibly using whereHas:

$venues = Venue::whereHas('location', function($query) use ($city) {
    $query->whereCityId($city->id);
})->get();
0
Captain Husayn Penguin On

It is important to remember that each eloquent query returns a collection, and hence you can use "collection methods" on the result. So as said in other answers, you need a Eager Loading which you ask for the attribute you want to sort on from another table based on your relationship and then on the result, which is a collection, you either use "sortBy" or "sortByDesc" methods.

You can look at an example below:

class Post extends Model {
        // imagine timpestamp table: id, publish, delete,
        // timestampable_id, timestampble_type
    public function timestamp()
    {
        return $this->morphOne(Timestamp::class, 'timestampable');
    }
}

and then in the view side of the stuff:

$posts = App\Post::with('timestamp')->get(); // we make Eager Loading
$posts = $posts->sortByDesc('timestamp.publish');
return view('blog.index', compact('posts'));