6

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?

5
  • are all relations between tables oneToOne? Commented Feb 23, 2018 at 17:17
  • @vpalade all realtions are oneToMany Commented Feb 23, 2018 at 17:20
  • I implemented you code in my computer and go a good result, I don't understand "but it does not work because when I do the following query, it returns some good objects and others with tableA = null:" plz explain what do you want Commented Feb 23, 2018 at 18:24
  • Well what happens to me is the following, let's say I have two "tableA" objects in my database (one with id = 1 and the other with id = 2) and the two objects have related "tableD" objects, when I get all the objects from tableD::with('tableA') the "tableD" objects that have the "tableA" with the id = 1 return with the "tableA" fine, but the "tableD" that have "tableA" with the id = 2 return "tableA" = null, is what my problem is understood? @Itisallyours Commented Feb 23, 2018 at 18:34
  • as I said, I have implemented the exact code and inserted two records for each tables like you said, there was no null object for table A, check your code again to see if id is properly set Commented Feb 23, 2018 at 18:53

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

0

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);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.