diff --git a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php index 4dd8059d072e..15de0bfe56dd 100644 --- a/src/Illuminate/Database/Eloquent/Relations/MorphTo.php +++ b/src/Illuminate/Database/Eloquent/Relations/MorphTo.php @@ -350,6 +350,57 @@ public function constrain(array $callbacks) return $this; } + /** + * Indicate that soft deleted models should be included in the results. + * + * @return $this + */ + public function withTrashed() + { + $callback = fn ($query) => $query->hasMacro('withTrashed') ? $query->withTrashed() : $query; + + $this->macroBuffer[] = [ + 'method' => 'when', + 'parameters' => [true, $callback], + ]; + + return $this->when(true, $callback); + } + + /** + * Indicate that soft deleted models should not be included in the results. + * + * @return $this + */ + public function withoutTrashed() + { + $callback = fn ($query) => $query->hasMacro('withoutTrashed') ? $query->withoutTrashed() : $query; + + $this->macroBuffer[] = [ + 'method' => 'when', + 'parameters' => [true, $callback], + ]; + + return $this->when(true, $callback); + } + + /** + * Indicate that only soft deleted models should be included in the results. + * + * @return $this + */ + public function onlyTrashed() + { + $callback = fn ($query) => $query->hasMacro('onlyTrashed') ? $query->onlyTrashed() : $query; + + $this->macroBuffer[] = [ + 'method' => 'when', + 'parameters' => [true, $callback], + ]; + + return $this->when(true, $callback); + } + /** * Replay stored macro calls on the actual related instance. * diff --git a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php index 5a512d7a7069..058f981b4b1a 100644 --- a/tests/Integration/Database/EloquentMorphEagerLoadingTest.php +++ b/tests/Integration/Database/EloquentMorphEagerLoadingTest.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\MorphTo; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; use Illuminate\Tests\Integration\Database\DatabaseTestCase; @@ -14,6 +15,7 @@ protected function defineDatabaseMigrationsAfterDatabaseRefreshed() { Schema::create('users', function (Blueprint $table) { $table->increments('id'); + $table->softDeletes(); }); Schema::create('posts', function (Blueprint $table) { @@ -25,6 +27,12 @@ protected function defineDatabaseMigrationsAfterDatabaseRefreshed() $table->increments('video_id'); }); + Schema::create('actions', function (Blueprint $table) { + $table->increments('id'); + $table->string('target_type'); + $table->integer('target_id'); + }); + Schema::create('comments', function (Blueprint $table) { $table->increments('id'); $table->string('commentable_type'); @@ -32,6 +40,7 @@ protected function defineDatabaseMigrationsAfterDatabaseRefreshed() }); $user = User::create(); + $user2 = User::forceCreate(['deleted_at' => now()]); $post = tap((new Post)->user()->associate($user))->save(); @@ -39,6 +48,9 @@ protected function defineDatabaseMigrationsAfterDatabaseRefreshed() (new Comment)->commentable()->associate($post)->save(); (new Comment)->commentable()->associate($video)->save(); + + (new Action)->target()->associate($video)->save(); + (new Action)->target()->associate($user2)->save(); } public function testWithMorphLoading() @@ -49,9 +61,13 @@ public function testWithMorphLoading() }]) ->get(); + $this->assertCount(2, $comments); + $this->assertTrue($comments[0]->relationLoaded('commentable')); + $this->assertInstanceOf(Post::class, $comments[0]->getRelation('commentable')); $this->assertTrue($comments[0]->commentable->relationLoaded('user')); $this->assertTrue($comments[1]->relationLoaded('commentable')); + $this->assertInstanceOf(Video::class, $comments[1]->getRelation('commentable')); } public function testWithMorphLoadingWithSingleRelation() @@ -65,6 +81,30 @@ public function testWithMorphLoadingWithSingleRelation() $this->assertTrue($comments[0]->relationLoaded('commentable')); $this->assertTrue($comments[0]->commentable->relationLoaded('user')); } + + public function testMorphLoadingMixedWithTrashedRelations() + { + $action = Action::query() + ->with('target') + ->get(); + + $this->assertCount(2, $action); + + $this->assertTrue($action[0]->relationLoaded('target')); + $this->assertInstanceOf(Video::class, $action[0]->getRelation('target')); + $this->assertTrue($action[1]->relationLoaded('target')); + $this->assertInstanceOf(User::class, $action[1]->getRelation('target')); + } +} + +class Action extends Model +{ + public $timestamps = false; + + public function target() + { + return $this->morphTo()->withTrashed(); + } } class Comment extends Model @@ -90,6 +130,8 @@ public function user() class User extends Model { + use SoftDeletes; + public $timestamps = false; }