Skip to content
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

[10.x] Allow utilising withTrashed(), withoutTrashed() and onlyTrashed() on MorphTo relationship even without SoftDeletes Model #47880

Merged
merged 10 commits into from Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/Illuminate/Database/Eloquent/Relations/MorphTo.php
Expand Up @@ -365,6 +365,57 @@ protected function replayMacros(Builder $query)
return $query;
}

/**
* Add the with-trashed to the query when available.
*
* @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);
}

/**
* Add the without-trashed to the query when available.
*
* @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);
}

/**
* Add the only-trashed to the query when available.
*
* @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);
}

/**
* Handle dynamic method calls to the relationship.
*
Expand Down
44 changes: 44 additions & 0 deletions tests/Integration/Database/EloquentMorphEagerLoadingTest.php
Expand Up @@ -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;
Expand All @@ -14,6 +15,7 @@ protected function defineDatabaseMigrationsAfterDatabaseRefreshed()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->softDeletes();
});

Schema::create('posts', function (Blueprint $table) {
Expand All @@ -25,20 +27,32 @@ 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');
$table->integer('commentable_id');
$table->string('target_type')->nullable();
$table->integer('target_id')->nullable();
crynobone marked this conversation as resolved.
Show resolved Hide resolved
});

$user = User::create();
$user2 = User::forceCreate(['deleted_at' => now()]);

$post = tap((new Post)->user()->associate($user))->save();

$video = Video::create();

(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()
Expand All @@ -49,9 +63,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()
Expand All @@ -65,6 +83,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
Expand All @@ -90,6 +132,8 @@ public function user()

class User extends Model
{
use SoftDeletes;

public $timestamps = false;
}

Expand Down