Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.5] "loadMissing" reload relation when loading nested relations #23027

Closed
Tantrisse opened this issue Feb 4, 2018 · 5 comments
Closed

[5.5] "loadMissing" reload relation when loading nested relations #23027

Tantrisse opened this issue Feb 4, 2018 · 5 comments

Comments

@Tantrisse
Copy link

Tantrisse commented Feb 4, 2018

  • Laravel Version: 5.5.33
  • PHP Version: 7.2

Description:

Hi !

I'd like to demonstrate an issue I have with loadMissing and nested relation.

The problem is pretty easy to reproduce so I doubt you are unaware of this but I can't find a workaround nor another issue here.

If you load a relation "inscriptions" and then loadMissing a nested relation of "inscriptions", it will reload the relation "inscriptions".

See below...

Steps To Reproduce:

Load a first time a relation using load or loadMissing :

Auth::user()->loadMissing('inscriptions');

Here the relation "inscriptions" is correctly loaded and set on the User object.

Then load a nested relation of the first model passing by a relation already loaded :

public function index(Request $request)
{
    \Auth::user()->loadMissing(['inscriptions.formation']);
    [...]
}

Here the user object already has the relation "inscriptions" but another query will hit the DB because the relation "inscriptions.formation" is not loaded as it is not really a relation but a composition of a relation and a nested relation.

Edit : To go further, is somewhere in my application I have this :

$myModel->load('relation.subRelation');

[...] // Some code later

$myModel->loadMissing('relation.subRelation');
// It is okay to do that, I may not be able to know if these relation are loaded,
// and loadMissing is here especially for this job
// (loading a relation only if it wasn't already loaded)

In this case, the "relation" and "subRelation" will be reloaded.

Is it going to be fixed by somehow checking the relations one by one for every level of nesting ?
Or is it too complicated and I should find a workaround ?

Thanks for your help ! 😄

@Tantrisse
Copy link
Author

Tantrisse commented Feb 4, 2018

I should probably create another issue for this other problem but I've another problem with "load" :
If you load 2 different nested relations of a model, only the last is kept.

Exemple :

$myModel->load(['relation.subRelation-A]);
[...] // Some code later
$myModel->load(['relation.subRelation-B]);

After the last load, "myModel->relation" will only have "subRelation-B" loaded, the key "subRelation-A" of myModel->relation doesn't even exists.

@staudenmeir
Copy link
Contributor

To solve your second problem, you have to combine them into one call:

$myModel->load(['relation.subRelation-A', 'relation.subRelation-B']);

@Tantrisse
Copy link
Author

Tantrisse commented Feb 7, 2018

Okay, I confirm @staudenmeir that loading the 2 relations at the same time with one load will load correctly the 2 relations.

The problem with this is I cannot ensure I will need the second sub relation right now !
This is why lazy-loading should do the job.


A basic example is :

Retrieve "Thing" from database
Load "Relation-1" and "Relation-1.subRelation-A" of "Thing"
Check if "Thing->Relation-1->subRelation-A->param1" is True

  • If it is True => Load "Relation-1.subRelation-B" of "Thing" and return informations of from "Relation-1.subRelation-A" and "Relation-1.subRelation-B"
  • If it is False => Return a response right now

If I use Thing->load(['Relation-1.subRelation-A', 'Relation-1.subRelation-B']); I cost 2 DB calls + PHP calls to build objects, link objects...

If I use Thing->load(['Relation-1.subRelation-A']); and "Thing->Relation-A->subRelation-A->param1" is False, I only cost 1 DB call and much less PHP calls.

On an application under heavy load (like an massively used API), I can't afford the cost of a useless DB and lot of PHP calls.

Hope you understand my point of view and why loading all the sub-relations ASAP is not feasible.

@staudenmeir
Copy link
Contributor

I took a look at the loadMissing method. As I see it, it's not trivial to make it handle nested relations, the *Many relationships are quite challenging.

You can load the second subrelation like this:

$thing->relation1->load('subRelation-B');

@staudenmeir
Copy link
Contributor

I proposed Collection::loadMissing(), which also brings support for nested relationships to Model::loadMissing(): #24166

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants