Rusben Guzman
Rusben Guzman

Reputation: 402

Load specific relations in a nested eager loading in laravel

I have the following related tables:

tableA 
  - id 
  - value

tableB 
  - id 
  - tableA_id
  - value

tableC 
  - id 
  - tableB_id
  - value


tableD 
  - id 
  - tableC_id
  - value

I normally use a nested eager loading to get the object of tableaA from tableD, for example:

$table_d = TableD::with('TableC.TableB.TableA')->find($id);

And I get an object like this:

{
    "id": 1,
    "value": "value",
    "tableC_id": 1,
    "tablec": {
                "id": 1,
                "value": "value",
                "tableB_id": 1,
                "tableb": {
                            "id": 1,
                            "value": "value",
                            "tableA_id": 1,
                            "tablea": {
                                        "id": 1,
                                        "value": "value"
                            }
                }
    }
}

What I want to achieve is to obtain only the object of table D, with its object from table A related, without having table C and table B in the final object, something like this:

{
    "id": 1,
    "value": "value",
    "tablea": {
                "id": 1,
                "value": "value"
                }
    }
}

I tried adding this function in the model file of Table D:

public function TableA()
    {
        return $this->belongsTo('App\Models\TableC', 'tableC_id')
                                ->join('tableB','tableC.tableB_id','=','tableB.id')
                                ->join('tableA','tableB.tableA_id','=','tableA.id')
                                ->select('tableA.id', 'tableA.value');
    }

but it does not work because when I do the following query, it returns some good objects and others with tableA = null:

$tables_d = TableD::with('TableA')->get()

Am I doing something wrong or is there another way to achieve what I want?

Upvotes: 6

Views: 829

Answers (3)

abr
abr

Reputation: 2129

You may be able to skip a table with this->hasManyThrough() but depending on what you really want as 'future features', you may want to have multiple relations with whatever code you desire according to your needs. QueryScopes aswell.

Upvotes: 2

vpalade
vpalade

Reputation: 1437

You can try to do this: - add a method in TableD Model:

public function table_a()
{
    return $this->TableC->TableB->TableA();
}

then use: TableD::with(table_a);

Upvotes: 0

Andrew Cotton
Andrew Cotton

Reputation: 425

One can generally use a has many through relationship for mapping tables when it is just two tables and a linking table between. You have yet another join beyond that so it won't really be much better than what you have currently.

Have you considered another mapping table from D to A directly or a bit of denormalization? If you always need to load it like that you might benefit from having a bit of duplicated fks to save on the joins.

This will really depend on your needs and it is not 3NF (third normal form), maybe it's not even 2NF, but that's why denormalization is like comma use...follow the rules generally but break them for specific reasons; in this case to reduce the number of required joins by duplicating a FK reference in a table.

https://laravel.com/docs/5.6/eloquent-relationships#has-many-through

Upvotes: 1

Related Questions