laraveleloquent

Laravel, getting deep relationships


I have the following structure:

'buildings' have many 'blocks' which have many 'units' which have many 'tenants'

I need to get a list of all tenants that live in a building.

Laravel provides hasMany and hasManyThrough commands that help you get collections of models which have direct relationship or are related through a single intermediate table but what if you want to get related elements of two, three, or any levels deep?

What is the proper way to achieve this using Laravel/Eloquent?


Solution

  • To find all the tenants in a given building, the easiest method would be to use JOIN clauses.

    I have assumed all of your relationships are hasMany inversed by belongsTo.

    $tenants = Tenant::select('tenants.*')
        ->join('units', 'units.id', '=', 'tenant.unit_id')
        ->join('blocks', 'blocks.id', '=', 'units.block_id')
        ->join('buildings', 'buildings.id', '=', 'blocks.building_id')
        ->where('buildings.id', 123)
        ->get();
    

    If this is something you'll use more than once, then I'd suggest creating a query scope on your Tenant model.

    class Tenant extends Eloquent
    {
        // ...
    
        public function scopeInBuilding($query, $buildingId)
        {
            return $query->select('tenants.*')
                ->join('units', 'units.id', '=', 'tenant.unit_id')
                ->join('blocks', 'blocks.id', '=', 'units.block_id')
                ->join('buildings', 'buildings.id', '=', 'blocks.building_id')
                ->where('buildings.id', $buildingId);
        }
    
        // ...
    }
    

    And you can use it as follows:

    $tenants = Tenant::inBuilding(123)->get();