From 4f39d2b6eb51d96c53300d752be8fa4ec68f53d1 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Thu, 12 Nov 2020 10:42:44 +1030 Subject: [PATCH 1/2] MorphTo relationship eager loading constraints --- .../Database/Eloquent/Relations/MorphTo.php | 26 ++++++ .../Database/EloquentMorphConstrainTest.php | 93 +++++++++++++++++++ 2 files changed, 119 insertions(+) create mode 100644 tests/Integration/Database/EloquentMorphConstrainTest.php diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 891c172dff69..57804fa3696a 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -51,6 +51,13 @@ class MorphTo extends BelongsTo */ protected $morphableEagerLoadCounts = []; + /** + * A map of constraints to apply for each individual morph type. + * + * @var array + */ + protected $morphableConstraints = []; + /** * Create a new morph to relationship instance. * @@ -133,6 +140,10 @@ protected function getResultsByType($type) (array) ($this->morphableEagerLoadCounts[get_class($instance)] ?? []) ); + if ($callback = $this->morphableConstraints[get_class($instance)] ?? null) { + $callback($query); + } + $whereIn = $this->whereInMethod($instance, $ownerKey); return $query->{$whereIn}( @@ -312,6 +323,21 @@ public function morphWithCount(array $withCount) return $this; } + /** + * Specify constraints on the query for a given morph type. + * + * @param array $with + * @return \Illuminate\Database\Eloquent\Relations\MorphTo + */ + public function constrain(array $callbacks) + { + $this->morphableConstraints = array_merge( + $this->morphableConstraints, $callbacks + ); + + return $this; + } + /** * Replay stored macro calls on the actual related instance. * diff --git a/tests/Integration/Database/EloquentMorphConstrainTest.php b/tests/Integration/Database/EloquentMorphConstrainTest.php new file mode 100644 index 000000000000..ac20d5fd467e --- /dev/null +++ b/tests/Integration/Database/EloquentMorphConstrainTest.php @@ -0,0 +1,93 @@ +increments('id'); + $table->boolean('post_visible'); + }); + + Schema::create('videos', function (Blueprint $table) { + $table->increments('id'); + $table->boolean('video_visible'); + }); + + Schema::create('comments', function (Blueprint $table) { + $table->increments('id'); + $table->string('commentable_type'); + $table->integer('commentable_id'); + }); + + $post1 = Post::create(['post_visible' => true]); + (new Comment)->commentable()->associate($post1)->save(); + + $post2 = Post::create(['post_visible' => false]); + (new Comment)->commentable()->associate($post2)->save(); + + $video1 = Video::create(['video_visible' => true]); + (new Comment)->commentable()->associate($video1)->save(); + + $video2 = Video::create(['video_visible' => false]); + (new Comment)->commentable()->associate($video2)->save(); + } + + public function testMorphConstraints() + { + $comments = Comment::query() + ->with(['commentable' => function (MorphTo $morphTo) { + $morphTo->constrain([ + Post::class => function ($query) { + $query->where('post_visible', true); + }, + Video::class => function ($query) { + $query->where('video_visible', true); + } + ]); + }]) + ->get(); + + $this->assertTrue($comments[0]->commentable->post_visible); + $this->assertNull($comments[1]->commentable); + $this->assertTrue($comments[2]->commentable->video_visible); + $this->assertNull($comments[3]->commentable); + } +} + +class Comment extends Model +{ + public $timestamps = false; + + public function commentable() + { + return $this->morphTo(); + } +} + +class Post extends Model +{ + public $timestamps = false; + protected $fillable = ['post_visible']; + protected $casts = ['post_visible' => 'boolean']; +} + +class Video extends Model +{ + public $timestamps = false; + protected $fillable = ['video_visible']; + protected $casts = ['video_visible' => 'boolean']; +} From 252872f66cd3b2cde15db92f8489e90a52a25763 Mon Sep 17 00:00:00 2001 From: Dries Vints Date: Thu, 12 Nov 2020 10:19:32 +0100 Subject: [PATCH 2/2] Update EloquentMorphConstrainTest.php --- tests/Integration/Database/EloquentMorphConstrainTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/Database/EloquentMorphConstrainTest.php b/tests/Integration/Database/EloquentMorphConstrainTest.php index ac20d5fd467e..e8e995d474c5 100644 --- a/tests/Integration/Database/EloquentMorphConstrainTest.php +++ b/tests/Integration/Database/EloquentMorphConstrainTest.php @@ -56,7 +56,7 @@ public function testMorphConstraints() }, Video::class => function ($query) { $query->where('video_visible', true); - } + }, ]); }]) ->get();