From b59d30d4db35bb8b4bf36fa12e9a02161e35cb16 Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Sun, 24 Nov 2024 21:44:49 +0200 Subject: [PATCH 1/8] Add eloquent relation autoload feature --- src/Illuminate/Database/Eloquent/Builder.php | 10 +- .../Database/Eloquent/Collection.php | 41 ++++ .../Eloquent/Concerns/HasAttributes.php | 4 + .../Eloquent/Concerns/HasRelationships.php | 142 ++++++++++++++ src/Illuminate/Database/Eloquent/Model.php | 28 +++ .../EloquentModelRelationAutoloadTest.php | 185 ++++++++++++++++++ 6 files changed, 407 insertions(+), 3 deletions(-) create mode 100644 tests/Integration/Database/EloquentModelRelationAutoloadTest.php diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index 77c0bd27d836..1f1c739a3a74 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -742,9 +742,13 @@ public function get($columns = ['*']) $models = $builder->eagerLoadRelations($models); } - return $this->applyAfterQueryCallbacks( - $builder->getModel()->newCollection($models) - ); + $collection = $builder->getModel()->newCollection($models); + + if (Model::alwaysAutoloadsRelations()) { + $collection->enableRelationAutoload(); + } + + return $this->applyAfterQueryCallbacks($collection); } /** diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index 1ae950cb9e73..e0f4e4ad6b4b 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -248,6 +248,31 @@ public function loadMissing($relations) return $this; } + /** + * Load a relationship path with types if it is not already eager loaded. + * + * @return void + */ + public function loadMissingRelationWithTypes(array $path) + { + list($name, $class) = array_shift($path); + + $this->filter(fn ($model) => ! is_null($model) && ! $model->relationLoaded($name) && $model::class === $class) + ->load($name); + + if (empty($path)) { + return; + } + + $models = $this->pluck($name)->whereNotNull(); + + if ($models->first() instanceof BaseCollection) { + $models = $models->collapse(); + } + + (new static($models))->loadMissingRelationWithTypes($path); + } + /** * Load a relationship path if it is not already eager loaded. * @@ -314,6 +339,22 @@ public function loadMorphCount($relation, $relations) return $this; } + /** + * Enable relation autoload for the collection. + * + * @return $this + */ + public function enableRelationAutoload() + { + $callback = fn ($path) => $this->loadMissingRelationWithTypes($path); + + $this + ->filter(fn ($model) => ! $model->hasRelationAutoloadCallback()) + ->each(fn ($model) => $model->usingRelationAutoloadCallback($this, $callback)); + + return $this; + } + /** * Determine if a key exists in the collection. * diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index c1ddc54c8f4b..5deddd89d9b9 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -549,6 +549,10 @@ public function getRelationValue($key) return; } + if ($this->handleRelationAutoload($key)) { + return $this->relations[$key]; + } + if ($this->preventsLazyLoading) { $this->handleLazyLoadingViolation($key); } diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php index c62132a26185..10abf56ab244 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php @@ -39,6 +39,20 @@ trait HasRelationships */ protected $touches = []; + /** + * The relationship autoload callback. + * + * @var ?Closure + */ + protected $relationAutoloadCallback = null; + + /** + * The relationship autoload context. + * + * @var ?Collection + */ + protected $relationAutoloadContext = null; + /** * The many to many relationship methods. * @@ -90,6 +104,132 @@ public static function resolveRelationUsing($name, Closure $callback) ); } + /** + * Set relation autoload callback for model and its relations. + * + * @param mixed $context + * @param Closure $callback + * @return $this + */ + public function usingRelationAutoloadCallback($context, Closure $callback) + { + $this->relationAutoloadContext = $context; + $this->relationAutoloadCallback = $callback; + + foreach ($this->relations as $key => $value) { + $this->applyRelationAutoloadCallbackToValue($key, $value); + } + + return $this; + } + + /** + * Get relation autoload context. + * + * @return mixed + */ + public function getRelationAutoloadContext() + { + return $this->relationAutoloadContext; + } + + /** + * Enable relation autoload for model and its relations if not already enabled. + * + * @return $this + */ + public function enableRelationAutoload() + { + if ($this->hasRelationAutoloadCallback()) { + return $this; + } + + $collection = new Collection([$this]); + + $this->usingRelationAutoloadCallback( + $collection, + fn ($path) => $collection->loadMissingRelationWithTypes($path) + ); + + return $this; + } + + /** + * Check if relation autoload callback is set. + * + * @return bool + */ + public function hasRelationAutoloadCallback() + { + return ! is_null($this->relationAutoloadCallback); + } + + /** + * Trigger relation autoload callback and check if relation is loaded. + * + * @param string $key + * @return bool + */ + protected function handleRelationAutoload($key) + { + if (! $this->hasRelationAutoloadCallback()) { + return false; + } + + $this->triggerRelationAutoloadCallback($key, []); + + return $this->relationLoaded($key); + } + + /** + * Trigger relation autoload callback. + * + * @param string $key + * @param array $keys + * @return void + */ + protected function triggerRelationAutoloadCallback($key, $keys) + { + call_user_func( + $this->relationAutoloadCallback, + array_merge([[$key, get_class($this)]], $keys) + ); + } + + /** + * Apply relation autoload callback to value. + * + * @param string $key + * @param mixed $values + * @return void + */ + protected function applyRelationAutoloadCallbackToValue($key, $values) + { + if (! $this->hasRelationAutoloadCallback() || ! $values) { + return; + } + + if ($values instanceof Model) { + $values = [$values]; + } + + if (! is_iterable($values)) { + return; + } + + $callback = fn (array $keys) => $this->triggerRelationAutoloadCallback($key, $keys); + + foreach ($values as $item) { + $context = $item->getRelationAutoloadContext(); + + // check if relation autoload contexts are different + // to avoid circular relation autoload + if (is_null($context) || $context !== $this->relationAutoloadContext) { + $item->usingRelationAutoloadCallback($this->relationAutoloadContext, $callback); + } + } + } + /** * Define a one-to-one relationship. * @@ -917,6 +1057,8 @@ public function setRelation($relation, $value) { $this->relations[$relation] = $value; + $this->applyRelationAutoloadCallbackToValue($relation, $value); + return $this; } diff --git a/src/Illuminate/Database/Eloquent/Model.php b/src/Illuminate/Database/Eloquent/Model.php index 7afa59933416..b3c8d2986039 100644 --- a/src/Illuminate/Database/Eloquent/Model.php +++ b/src/Illuminate/Database/Eloquent/Model.php @@ -173,6 +173,13 @@ abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToSt */ protected static $modelsShouldPreventLazyLoading = false; + /** + * Indicates whether relations should be automatically loaded on all models. + * + * @var bool + */ + protected static $modelsShouldAlwaysAutoloadRelations = false; + /** * The callback that is responsible for handling lazy loading violations. * @@ -442,6 +449,17 @@ public static function preventLazyLoading($value = true) static::$modelsShouldPreventLazyLoading = $value; } + /** + * Determine if model relationships should be automatically loaded. + * + * @param bool $value + * @return void + */ + public static function alwaysAutoloadRelations($value = true) + { + static::$modelsShouldAlwaysAutoloadRelations = $value; + } + /** * Register a callback that is responsible for handling lazy loading violations. * @@ -2208,6 +2226,16 @@ public static function preventsLazyLoading() return static::$modelsShouldPreventLazyLoading; } + /** + * Determine if relations autoload is enabled. + * + * @return bool + */ + public static function alwaysAutoloadsRelations() + { + return static::$modelsShouldAlwaysAutoloadRelations; + } + /** * Determine if discarding guarded attribute fills is disabled. * diff --git a/tests/Integration/Database/EloquentModelRelationAutoloadTest.php b/tests/Integration/Database/EloquentModelRelationAutoloadTest.php new file mode 100644 index 000000000000..3b88bb8f7285 --- /dev/null +++ b/tests/Integration/Database/EloquentModelRelationAutoloadTest.php @@ -0,0 +1,185 @@ +increments('id'); + }); + + Schema::create('videos', function (Blueprint $table) { + $table->increments('id'); + }); + + Schema::create('comments', function (Blueprint $table) { + $table->increments('id'); + $table->unsignedInteger('parent_id')->nullable(); + $table->morphs('commentable'); + }); + + Schema::create('likes', function (Blueprint $table) { + $table->increments('id'); + $table->morphs('likeable'); + }); + } + + public function testRelationAutoload() + { + $post1 = Post::create(); + $comment1 = $post1->comments()->create(['parent_id' => null]); + $comment2 = $post1->comments()->create(['parent_id' => $comment1->id]); + $comment2->likes()->create(); + $comment2->likes()->create(); + + $post2 = Post::create(); + $comment3 = $post2->comments()->create(['parent_id' => null]); + $comment3->likes()->create(); + + $posts = Post::get(); + + DB::enableQueryLog(); + + $likes = []; + + $posts->enableRelationAutoload(); + + foreach ($posts as $post) { + foreach ($post->comments as $comment) { + $likes = array_merge($likes, $comment->likes->all()); + } + } + + $this->assertCount(2, DB::getQueryLog()); + $this->assertCount(3, $likes); + $this->assertTrue($posts[0]->comments[0]->relationLoaded('likes')); + } + + public function testRelationAutoloadVariousNestedMorphRelations() + { + tap(Post::create(), function ($post) { + $post->likes()->create(); + $post->comments()->create(); + tap($post->comments()->create(), function ($comment) { + $comment->likes()->create(); + $comment->likes()->create(); + }); + }); + + tap(Post::create(), function ($post) { + $post->likes()->create(); + tap($post->comments()->create(), function ($comment) { + $comment->likes()->create(); + }); + }); + + tap(Video::create(), function ($video) { + tap($video->comments()->create(), function ($comment) { + $comment->likes()->create(); + }); + }); + + tap(Video::create(), function ($video) { + tap($video->comments()->create(), function ($comment) { + $comment->likes()->create(); + }); + }); + + Post::alwaysAutoloadRelations(); + + $likes = Like::get(); + + DB::enableQueryLog(); + + $videos = []; + $videoLike = null; + +// $likes->enableRelationAutoload(); + + foreach ($likes as $like) { + $likeable = $like->likeable; + + if (($likeable instanceof Comment) && ($likeable->commentable instanceof Video)) { + $videos[] = $likeable->commentable; + $videoLike = $like; + } + } + + $this->assertCount(4, DB::getQueryLog()); + $this->assertCount(2, $videos); + $this->assertTrue($videoLike->relationLoaded('likeable')); + $this->assertTrue($videoLike->likeable->relationLoaded('commentable')); + } +} + +class Comment extends Model +{ + public $timestamps = false; + + protected $guarded = []; + + public function parent() + { + return $this->belongsTo(self::class); + } + + public function likes() + { + return $this->morphMany(Like::class, 'likeable'); + } + + public function commentable() + { + return $this->morphTo(); + } +} + +class Post extends Model +{ + public $timestamps = false; + + public function comments() + { + return $this->morphMany(Comment::class, 'commentable'); + } + + public function likes() + { + return $this->morphMany(Like::class, 'likeable'); + } +} + +class Video extends Model +{ + public $timestamps = false; + + public function comments() + { + return $this->morphMany(Comment::class, 'commentable'); + } + + public function likes() + { + return $this->morphMany(Like::class, 'likeable'); + } +} + +class Like extends Model +{ + public $timestamps = false; + + protected $guarded = []; + + public function likeable() + { + return $this->morphTo(); + } +} From 06eaa3ff4753a8e854d2779f5c58eee114924246 Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Sun, 24 Nov 2024 22:21:53 +0200 Subject: [PATCH 2/8] update tests --- .../Database/EloquentModelRelationAutoloadTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/Integration/Database/EloquentModelRelationAutoloadTest.php b/tests/Integration/Database/EloquentModelRelationAutoloadTest.php index 3b88bb8f7285..5bb92bdd7731 100644 --- a/tests/Integration/Database/EloquentModelRelationAutoloadTest.php +++ b/tests/Integration/Database/EloquentModelRelationAutoloadTest.php @@ -93,8 +93,6 @@ public function testRelationAutoloadVariousNestedMorphRelations() }); }); - Post::alwaysAutoloadRelations(); - $likes = Like::get(); DB::enableQueryLog(); @@ -102,7 +100,7 @@ public function testRelationAutoloadVariousNestedMorphRelations() $videos = []; $videoLike = null; -// $likes->enableRelationAutoload(); + $likes->enableRelationAutoload(); foreach ($likes as $like) { $likeable = $like->likeable; From f4e09a731b9d22f82062be813f55bc0f8353d91f Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Sun, 24 Nov 2024 22:40:37 +0200 Subject: [PATCH 3/8] update tests --- .../DatabaseEloquentBelongsToManyWithCastedAttributesTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php b/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php index c7cab6453dfb..08f1bd45a56e 100644 --- a/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php +++ b/tests/Database/DatabaseEloquentBelongsToManyWithCastedAttributesTest.php @@ -27,6 +27,7 @@ public function testModelsAreProperlyMatchedToParents() $model1->shouldReceive('getAttribute')->with('foo')->passthru(); $model1->shouldReceive('hasGetMutator')->andReturn(false); $model1->shouldReceive('hasAttributeMutator')->andReturn(false); + $model1->shouldReceive('hasRelationAutoloadCallback')->andReturn(false); $model1->shouldReceive('getCasts')->andReturn([]); $model1->shouldReceive('getRelationValue', 'relationLoaded', 'relationResolver', 'setRelation', 'isRelation')->passthru(); @@ -36,6 +37,7 @@ public function testModelsAreProperlyMatchedToParents() $model2->shouldReceive('getAttribute')->with('foo')->passthru(); $model2->shouldReceive('hasGetMutator')->andReturn(false); $model2->shouldReceive('hasAttributeMutator')->andReturn(false); + $model2->shouldReceive('hasRelationAutoloadCallback')->andReturn(false); $model2->shouldReceive('getCasts')->andReturn([]); $model2->shouldReceive('getRelationValue', 'relationLoaded', 'relationResolver', 'setRelation', 'isRelation')->passthru(); From 479c7073f65b763916bf1bc75673776545c67aae Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Sun, 24 Nov 2024 22:43:43 +0200 Subject: [PATCH 4/8] fix cs --- src/Illuminate/Database/Eloquent/Collection.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index e0f4e4ad6b4b..307738b2228a 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -255,7 +255,7 @@ public function loadMissing($relations) */ public function loadMissingRelationWithTypes(array $path) { - list($name, $class) = array_shift($path); + [$name, $class] = array_shift($path); $this->filter(fn ($model) => ! is_null($model) && ! $model->relationLoaded($name) && $model::class === $class) ->load($name); @@ -342,7 +342,7 @@ public function loadMorphCount($relation, $relations) /** * Enable relation autoload for the collection. * - * @return $this + * @return $this */ public function enableRelationAutoload() { From ce415d122b6d4b92351e80c97e3fbe3b0ca290dc Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Sun, 24 Nov 2024 22:47:12 +0200 Subject: [PATCH 5/8] fix cs --- .../Eloquent/Concerns/HasRelationships.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php index 10abf56ab244..ef57355105e1 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php @@ -107,8 +107,8 @@ public static function resolveRelationUsing($name, Closure $callback) /** * Set relation autoload callback for model and its relations. * - * @param mixed $context - * @param Closure $callback + * @param mixed $context + * @param Closure $callback * @return $this */ public function usingRelationAutoloadCallback($context, Closure $callback) @@ -167,7 +167,7 @@ public function hasRelationAutoloadCallback() /** * Trigger relation autoload callback and check if relation is loaded. * - * @param string $key + * @param string $key * @return bool */ protected function handleRelationAutoload($key) @@ -184,8 +184,8 @@ protected function handleRelationAutoload($key) /** * Trigger relation autoload callback. * - * @param string $key - * @param array $keys + * @param string $key + * @param array $keys * @return void */ protected function triggerRelationAutoloadCallback($key, $keys) @@ -199,8 +199,8 @@ protected function triggerRelationAutoloadCallback($key, $keys) /** * Apply relation autoload callback to value. * - * @param string $key - * @param mixed $values + * @param string $key + * @param mixed $values * @return void */ protected function applyRelationAutoloadCallbackToValue($key, $values) From 6cdc3c447a4447cd206c3bf19c7faffbb860fc6d Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Mon, 25 Nov 2024 23:39:05 +0200 Subject: [PATCH 6/8] Rename alwaysAutoloadRelations method to globalAutoloadRelations --- src/Illuminate/Database/Eloquent/Builder.php | 2 +- src/Illuminate/Database/Eloquent/Model.php | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index 1f1c739a3a74..dc4dd152d547 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -744,7 +744,7 @@ public function get($columns = ['*']) $collection = $builder->getModel()->newCollection($models); - if (Model::alwaysAutoloadsRelations()) { + if (Model::isAutoloadingRelationsGlobally()) { $collection->enableRelationAutoload(); } diff --git a/src/Illuminate/Database/Eloquent/Model.php b/src/Illuminate/Database/Eloquent/Model.php index b3c8d2986039..312dc755ef1a 100644 --- a/src/Illuminate/Database/Eloquent/Model.php +++ b/src/Illuminate/Database/Eloquent/Model.php @@ -178,7 +178,7 @@ abstract class Model implements Arrayable, ArrayAccess, CanBeEscapedWhenCastToSt * * @var bool */ - protected static $modelsShouldAlwaysAutoloadRelations = false; + protected static $modelsShouldGlobalAutoloadRelations = false; /** * The callback that is responsible for handling lazy loading violations. @@ -455,9 +455,9 @@ public static function preventLazyLoading($value = true) * @param bool $value * @return void */ - public static function alwaysAutoloadRelations($value = true) + public static function globalAutoloadRelations($value = true) { - static::$modelsShouldAlwaysAutoloadRelations = $value; + static::$modelsShouldGlobalAutoloadRelations = $value; } /** @@ -2231,9 +2231,9 @@ public static function preventsLazyLoading() * * @return bool */ - public static function alwaysAutoloadsRelations() + public static function isAutoloadingRelationsGlobally() { - return static::$modelsShouldAlwaysAutoloadRelations; + return static::$modelsShouldGlobalAutoloadRelations; } /** From ada7a8dd3bf604d96c41aa2d4ba2d2f99657d9ef Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Tue, 26 Nov 2024 11:29:38 +0200 Subject: [PATCH 7/8] Rename enableRelationAutoload method to withRelationAutoload --- src/Illuminate/Database/Eloquent/Builder.php | 2 +- src/Illuminate/Database/Eloquent/Collection.php | 2 +- .../Database/Eloquent/Concerns/HasRelationships.php | 2 +- .../Database/EloquentModelRelationAutoloadTest.php | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index dc4dd152d547..4437650016ba 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -745,7 +745,7 @@ public function get($columns = ['*']) $collection = $builder->getModel()->newCollection($models); if (Model::isAutoloadingRelationsGlobally()) { - $collection->enableRelationAutoload(); + $collection->withRelationAutoload(); } return $this->applyAfterQueryCallbacks($collection); diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index 307738b2228a..b800e908163f 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -344,7 +344,7 @@ public function loadMorphCount($relation, $relations) * * @return $this */ - public function enableRelationAutoload() + public function withRelationAutoload() { $callback = fn ($path) => $this->loadMissingRelationWithTypes($path); diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php index ef57355105e1..e950fe43d466 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php @@ -138,7 +138,7 @@ public function getRelationAutoloadContext() * * @return $this */ - public function enableRelationAutoload() + public function withRelationAutoload() { if ($this->hasRelationAutoloadCallback()) { return $this; diff --git a/tests/Integration/Database/EloquentModelRelationAutoloadTest.php b/tests/Integration/Database/EloquentModelRelationAutoloadTest.php index 5bb92bdd7731..7891eb30201d 100644 --- a/tests/Integration/Database/EloquentModelRelationAutoloadTest.php +++ b/tests/Integration/Database/EloquentModelRelationAutoloadTest.php @@ -50,7 +50,7 @@ public function testRelationAutoload() $likes = []; - $posts->enableRelationAutoload(); + $posts->withRelationAutoload(); foreach ($posts as $post) { foreach ($post->comments as $comment) { @@ -100,7 +100,7 @@ public function testRelationAutoloadVariousNestedMorphRelations() $videos = []; $videoLike = null; - $likes->enableRelationAutoload(); + $likes->withRelationAutoload(); foreach ($likes as $like) { $likeable = $like->likeable; From 7c4606824d85b50541ee83137f485a9cbe51dfc6 Mon Sep 17 00:00:00 2001 From: Sergiy Litvinchuk Date: Wed, 27 Nov 2024 18:32:59 +0200 Subject: [PATCH 8/8] Optimize withRelationAutoload method --- src/Illuminate/Database/Eloquent/Collection.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Collection.php b/src/Illuminate/Database/Eloquent/Collection.php index b800e908163f..5cfedc6c212d 100755 --- a/src/Illuminate/Database/Eloquent/Collection.php +++ b/src/Illuminate/Database/Eloquent/Collection.php @@ -348,9 +348,8 @@ public function withRelationAutoload() { $callback = fn ($path) => $this->loadMissingRelationWithTypes($path); - $this - ->filter(fn ($model) => ! $model->hasRelationAutoloadCallback()) - ->each(fn ($model) => $model->usingRelationAutoloadCallback($this, $callback)); + $this->each(fn ($model) => $model->hasRelationAutoloadCallback() + || $model->usingRelationAutoloadCallback($this, $callback)); return $this; }