From 0b891475133e8e427a5ad61dc4be80a99ecf8424 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Wed, 29 May 2019 10:43:59 +0200 Subject: [PATCH 1/8] Add support for typed eager loads --- .../Database/Eloquent/Relations/MorphTo.php | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 6c08ef3e04c0..2768594a5d29 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -37,6 +37,13 @@ class MorphTo extends BelongsTo */ protected $macroBuffer = []; + /** + * A map of relations to load for each individual morph type + * + * @var array + */ + protected $typedEagerLoads = []; + /** * Create a new morph to relationship instance. * @@ -111,7 +118,10 @@ protected function getResultsByType($type) $query = $this->replayMacros($instance->newQuery()) ->mergeConstraintsFrom($this->getQuery()) - ->with($this->getQuery()->getEagerLoads()); + ->with(array_merge( + $this->getQuery()->getEagerLoads(), + $this->typedEagerLoads[get_class($instance)] ?? [] + )); return $query->whereIn( $instance->getTable().'.'.$ownerKey, $this->gatherKeysByType($type) @@ -253,6 +263,24 @@ public function getDictionary() return $this->dictionary; } + /** + * Specify which relations to load for a given morph type + * + * @param string $modelClass + * @param array $with + * + * @return \Illuminate\Database\Eloquent\Relations\MorphTo + */ + public function withMorph(string $modelClass, array $with): self + { + $this->typedEagerLoads[$modelClass] = array_merge( + $this->typedEagerLoads[$modelClass] ?? [], + $with + ); + + return $this; + } + /** * Replay stored macro calls on the actual related instance. * From b39a01d2962edf2d114cf81c38f4b441479d4a4e Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Wed, 29 May 2019 11:01:09 +0200 Subject: [PATCH 2/8] Fix styleCI errors --- src/Illuminate/Database/Eloquent/Relations/MorphTo.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 2768594a5d29..4c45e1fd1292 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -38,7 +38,7 @@ class MorphTo extends BelongsTo protected $macroBuffer = []; /** - * A map of relations to load for each individual morph type + * A map of relations to load for each individual morph type. * * @var array */ @@ -264,7 +264,7 @@ public function getDictionary() } /** - * Specify which relations to load for a given morph type + * Specify which relations to load for a given morph type. * * @param string $modelClass * @param array $with From b80a1c85757b209b082a94b1a965b26f4182b05d Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Wed, 29 May 2019 11:09:40 +0200 Subject: [PATCH 3/8] Add test --- .../EloquentMorphEagerLoadingTest.php | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/Integration/Database/EloquentMorphEagerLoadingTest.php diff --git a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php new file mode 100644 index 000000000000..97305cbabb4d --- /dev/null +++ b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php @@ -0,0 +1,94 @@ +increments('id'); + }); + + Schema::create('posts', function (Blueprint $table) { + $table->increments('post_id'); + $table->unsignedInteger('user_id'); + }); + + Schema::create('videos', function (Blueprint $table) { + $table->increments('video_id'); + }); + + Schema::create('comments', function (Blueprint $table) { + $table->increments('id'); + $table->string('commentable_type'); + $table->integer('commentable_id'); + }); + + $user = User::create(); + + $post = tap((new Post)->user()->associate($user))->save(); + + $video = Video::create(); + + (new Comment)->commentable()->associate($post)->save(); + (new Comment)->commentable()->associate($video)->save(); + } + + public function test_with_morph_loading() + { + $comments = Comment::query() + ->with(['commentable' => function (MorphTo $morphTo) { + $morphTo->withMorph(Post::class, ['user']); + }]) + ->get(); + + $this->assertTrue($comments[0]->relationLoaded('commentable')); + $this->assertTrue($comments[0]->commentable->relationLoaded('user')); + $this->assertTrue($comments[1]->relationLoaded('commentable')); + } +} + +class Comment extends Model +{ + public $timestamps = false; + + public function commentable() + { + return $this->morphTo(); + } +} + +class Post extends Model +{ + public $timestamps = false; + protected $primaryKey = 'post_id'; + + public function user() + { + return $this->belongsTo(User::class); + } +} + +class User extends Model +{ + public $timestamps = false; +} + +class Video extends Model +{ + public $timestamps = false; + protected $primaryKey = 'video_id'; +} From 544891bba4bb97a68f752fcde675bdb2c21c4cfc Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Wed, 29 May 2019 13:22:13 +0200 Subject: [PATCH 4/8] Remove return type --- src/Illuminate/Database/Eloquent/Relations/MorphTo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 4c45e1fd1292..e6e28343dfc8 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -271,7 +271,7 @@ public function getDictionary() * * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function withMorph(string $modelClass, array $with): self + public function withMorph(string $modelClass, array $with) { $this->typedEagerLoads[$modelClass] = array_merge( $this->typedEagerLoads[$modelClass] ?? [], From f6617715417d364123782c1504ee76611ac040ff Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Wed, 29 May 2019 13:48:11 +0200 Subject: [PATCH 5/8] StyleCI --- tests/Integration/Database/EloquentMorphEagerLoadingTest.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php index 97305cbabb4d..3013deb45804 100644 --- a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php +++ b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php @@ -2,17 +2,16 @@ namespace Illuminate\Tests\Integration\Database\EloquentMorphToLazyEagerLoadingTest; -use DB; -use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Support\Facades\Schema; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Tests\Integration\Database\DatabaseTestCase; /** * @group integration */ -class EloquentMorphToLazyEagerLoadingTest extends DatabaseTestCase +class EloquentMorphEagerLoadingTest extends DatabaseTestCase { protected function setUp(): void { From 5f1dc4e48a621418b76850b24895f3ad254dd771 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Thu, 30 May 2019 15:39:42 +0200 Subject: [PATCH 6/8] Follow loadMorph syntax --- src/Illuminate/Database/Eloquent/Relations/MorphTo.php | 6 +++--- .../Integration/Database/EloquentMorphEagerLoadingTest.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index e6e28343dfc8..1ea2ccc3cfb3 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -271,10 +271,10 @@ public function getDictionary() * * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ - public function withMorph(string $modelClass, array $with) + public function withMorph(array $with) { - $this->typedEagerLoads[$modelClass] = array_merge( - $this->typedEagerLoads[$modelClass] ?? [], + $this->typedEagerLoads = array_merge( + $this->typedEagerLoads, $with ); diff --git a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php index 3013deb45804..2e63143b88b0 100644 --- a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php +++ b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php @@ -50,7 +50,7 @@ public function test_with_morph_loading() { $comments = Comment::query() ->with(['commentable' => function (MorphTo $morphTo) { - $morphTo->withMorph(Post::class, ['user']); + $morphTo->withMorph([Post::class =>['user']]); }]) ->get(); From a6700e5b8325e6de10fc0637d774853b7cc997c9 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Fri, 31 May 2019 08:40:45 +0200 Subject: [PATCH 7/8] Docblock cleanup and support single relations --- .../Database/Eloquent/Relations/MorphTo.php | 4 +--- .../Database/EloquentMorphEagerLoadingTest.php | 14 +++++++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 1ea2ccc3cfb3..28867c7e4d90 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -120,7 +120,7 @@ protected function getResultsByType($type) ->mergeConstraintsFrom($this->getQuery()) ->with(array_merge( $this->getQuery()->getEagerLoads(), - $this->typedEagerLoads[get_class($instance)] ?? [] + (array) ($this->typedEagerLoads[get_class($instance)] ?? []) )); return $query->whereIn( @@ -266,9 +266,7 @@ public function getDictionary() /** * Specify which relations to load for a given morph type. * - * @param string $modelClass * @param array $with - * * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ public function withMorph(array $with) diff --git a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php index 2e63143b88b0..b7ba197a6f75 100644 --- a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php +++ b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php @@ -50,7 +50,7 @@ public function test_with_morph_loading() { $comments = Comment::query() ->with(['commentable' => function (MorphTo $morphTo) { - $morphTo->withMorph([Post::class =>['user']]); + $morphTo->withMorph([Post::class => ['user']]); }]) ->get(); @@ -58,6 +58,18 @@ public function test_with_morph_loading() $this->assertTrue($comments[0]->commentable->relationLoaded('user')); $this->assertTrue($comments[1]->relationLoaded('commentable')); } + + public function test_with_morph_loading_with_single_relation() + { + $comments = Comment::query() + ->with(['commentable' => function (MorphTo $morphTo) { + $morphTo->withMorph([Post::class => 'user']); + }]) + ->get(); + + $this->assertTrue($comments[0]->relationLoaded('commentable')); + $this->assertTrue($comments[0]->commentable->relationLoaded('user')); + } } class Comment extends Model From b45bf1049c6498142810bc993f1ba79d94c1a2e5 Mon Sep 17 00:00:00 2001 From: Brent Roose Date: Fri, 31 May 2019 14:34:34 +0200 Subject: [PATCH 8/8] Update src/Illuminate/Database/Eloquent/Relations/MorphTo.php Co-Authored-By: Dries Vints --- src/Illuminate/Database/Eloquent/Relations/MorphTo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 28867c7e4d90..8162dc8df7a9 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -266,7 +266,7 @@ public function getDictionary() /** * Specify which relations to load for a given morph type. * - * @param array $with + * @param array $with * @return \Illuminate\Database\Eloquent\Relations\MorphTo */ public function withMorph(array $with)