Skip to content

Double query when using $with in model, and SerializesModels trait #55546

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

Closed
alexmontoanelli opened this issue Apr 24, 2025 · 5 comments
Closed

Comments

@alexmontoanelli
Copy link
Contributor

Laravel Version

12.x

PHP Version

8.3

Database Driver & Version

No response

Description

If you have a model, with the 'public $with' attribute to autoEagerLoad relationships,
when, unserializing a model in (queue worker, after a job pickup), the Model itself load the relationship ($with attribute), and if the relationship was loaded before the job dispatched, the Trait SerializesAndRestoresModelIdentifiers will load that relationship again.

In my investigations, the SerializesAndRestoresModelIdentifiers::110, is the issue where
he tries to load the relation.

If he use loadMissing, the behavior is OK, no relation already loaded will be loaded.

Steps To Reproduce

class User extends Model {

  public $with = 'country';

  public function country() : HasOne {
    return $this->hasOne(Country::class);
 }

}

class Country extends Model {
}


//load the user
$user = User::find(1);

//$user now has country RelationShip autoloaded loaded


//dispatch a job
$job = new SomeJob($user);

//the model will be serialized
dispatch($job);


//when job is picked up by a worker
//the model with be loaded again from database,
//the $with  will be loaded by the model itset
//the Trait, will reload the relation again (SerializesAndRestoresModelIdentifiers line 110)

@AndrewMast
Copy link
Contributor

So maybe we should ignore the $with when unserializing models? Because when it was serialized it would already have the relationships loaded?

Or maybe we can change SerializesAndRestoresModelIdentifiers.php to use $model->loadMissing() instead of $model->load()?

@alexmontoanelli
Copy link
Contributor Author

I don't know what is the best strategy, but I will go with change from load() to loadMissing().

We also need to test, if this is happening when serializing a collection ...

AndrewMast added a commit to AndrewMast/laravel-testing that referenced this issue Apr 24, 2025
@AndrewMast
Copy link
Contributor

AndrewMast commented Apr 24, 2025

I created a repo that reproduces this error: https://github.com/AndrewMast/laravel-testing/tree/issue-55546 (see diff).

Steps to reproduce after cloning:

  1. php artisan migrate:fresh --seed
  2. php artisan tinker and run User::first()->dispatchTesting();
  3. php artisan queue:work to run the dispatched job

As brought up in the issue, these queries are run:

select * from "users" where "users"."id" = 1 limit 1
select * from "countries" where "countries"."id" in (1)
select * from "countries" where "countries"."id" in (1)

When changing load to loadMissing in SerializesAndRestoresModelIdentifiers.php on line 110, it only fetches the country once:

select * from "users" where "users"."id" = 1 limit 1
select * from "countries" where "countries"."id" in (1)

I plan on opening a PR to fix this issue.

@AndrewMast
Copy link
Contributor

@alexmontoanelli This should be fixed with #55547 being merged.

@AndrewMast
Copy link
Contributor

Should be officially fixed with v12.11.0.

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

3 participants