/
githubmirror
/
framework
Обзор
Документация
Войти
/
githubmirror
/
framework
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
13.x
tests/Database/DatabaseEloquentSoftDeletesIntegrationTest.php
1 181 строка
37 KB
Jason McCreary
[13.x] Mockery cleanup (#61117)
10 авг 2026, 20:23
Не верифицирован
10 авг 2026, 20:23
2ee40ee
Код
Авторство
О чём код?
<?php namespace Illuminate\Tests\Database; use BadMethodCallException; use Exception; use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Database\Eloquent\Model as Eloquent; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletingScope; use Illuminate\Database\Query\Builder; use Illuminate\Events\Dispatcher; use Illuminate\Pagination\CursorPaginator; use Illuminate\Pagination\Paginator; use Illuminate\Support\Carbon; use Mockery; use Mockery\MockInterface; use PHPUnit\Framework\TestCase; class DatabaseEloquentSoftDeletesIntegrationTest extends TestCase { protected function setUp(): void { $db = new DB; $db->addConnection([ 'driver' => 'sqlite', 'database' => ':memory:', ]); $db->bootEloquent(); $db->setAsGlobal(); $this->createSchema(); } /** * Setup the database schema. * * @return void */ public function createSchema() { $this->schema()->create('users', function ($table) { $table->increments('id'); $table->integer('user_id')->nullable(); // circular reference to parent User $table->integer('group_id')->nullable(); $table->string('email')->unique(); $table->timestamps(); $table->softDeletes(); }); $this->schema()->create('posts', function ($table) { $table->increments('id'); $table->integer('user_id'); $table->string('title'); $table->integer('priority')->default(0); $table->timestamps(); $table->softDeletes(); }); $this->schema()->create('comments', function ($table) { $table->increments('id'); $table->integer('owner_id')->nullable(); $table->string('owner_type')->nullable(); $table->integer('post_id'); $table->string('body'); $table->timestamps(); $table->softDeletes(); }); $this->schema()->create('addresses', function ($table) { $table->increments('id'); $table->integer('user_id'); $table->string('address'); $table->timestamps(); $table->softDeletes(); }); $this->schema()->create('groups', function ($table) { $table->increments('id'); $table->string('name'); $table->timestamps(); $table->softDeletes(); }); } /** * Tear down the database schema. * * @return void */ protected function tearDown(): void { $this->schema()->drop('users'); $this->schema()->drop('posts'); $this->schema()->drop('comments'); } /** * Tests... */ public function testSoftDeletesAreNotRetrieved() { $this->createUsers(); $users = SoftDeletesTestUser::all(); $this->assertCount(1, $users); $this->assertEquals(2, $users->first()->id); $this->assertNull(SoftDeletesTestUser::find(1)); } public function testSoftDeletesAreNotRetrievedFromBaseQuery() { $this->createUsers(); $query = SoftDeletesTestUser::query()->toBase(); $this->assertInstanceOf(Builder::class, $query); $this->assertCount(1, $query->get()); } public function testSoftDeletesAreNotRetrievedFromRelationshipBaseQuery() { [, $abigail] = $this->createUsers(); $abigail->posts()->create(['title' => 'Foo']); $abigail->posts()->create(['title' => 'Bar'])->delete(); $query = $abigail->posts()->toBase(); $this->assertInstanceOf(Builder::class, $query); $this->assertCount(1, $query->get()); } public function testSoftDeletesAreNotRetrievedFromBuilderHelpers() { $this->createUsers(); $count = 0; $query = SoftDeletesTestUser::query(); $query->chunk(2, function ($user) use (&$count) { $count += count($user); }); $this->assertEquals(1, $count); $query = SoftDeletesTestUser::query(); $this->assertCount(1, $query->pluck('email')->all()); Paginator::currentPageResolver(function () { return 1; }); CursorPaginator::currentCursorResolver(function () { return null; }); $query = SoftDeletesTestUser::query(); $this->assertCount(1, $query->paginate(2)->all()); $query = SoftDeletesTestUser::query(); $this->assertCount(1, $query->simplePaginate(2)->all()); $query = SoftDeletesTestUser::query(); $this->assertCount(1, $query->cursorPaginate(2)->all()); $this->assertEquals(0, SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->increment('id')); $this->assertEquals(0, SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->decrement('id')); } public function testWithTrashedReturnsAllRecords() { $this->createUsers(); $this->assertCount(2, SoftDeletesTestUser::withTrashed()->get()); $this->assertInstanceOf(Eloquent::class, SoftDeletesTestUser::withTrashed()->find(1)); } public function testWithTrashedAcceptsAnArgument() { $this->createUsers(); $this->assertCount(1, SoftDeletesTestUser::withTrashed(false)->get()); $this->assertCount(2, SoftDeletesTestUser::withTrashed(true)->get()); } public function testDeleteSetsDeletedColumn() { $this->createUsers(); $this->assertInstanceOf(Carbon::class, SoftDeletesTestUser::withTrashed()->find(1)->deleted_at); $this->assertNull(SoftDeletesTestUser::find(2)->deleted_at); } public function testForceDeleteActuallyDeletesRecords() { $this->createUsers(); SoftDeletesTestUser::find(2)->forceDelete(); $users = SoftDeletesTestUser::withTrashed()->get(); $this->assertCount(1, $users); $this->assertEquals(1, $users->first()->id); } public function testForceDeleteUpdateExistsProperty() { $this->createUsers(); $user = SoftDeletesTestUser::find(2); $this->assertTrue($user->exists); $user->forceDelete(); $this->assertFalse($user->exists); } public function testForceDeleteDoesntUpdateExistsPropertyIfFailed() { $user = new class() extends SoftDeletesTestUser { public $exists = true; public function newModelQuery() { return Mockery::spy(parent::newModelQuery(), function (MockInterface $mock) { $mock->expects('forceDelete')->andThrow(new Exception()); }); } }; $this->assertTrue($user->exists); try { $user->forceDelete(); } catch (Exception) { } $this->assertTrue($user->exists); } public function testForceDestroyFullyDeletesRecord() { $this->createUsers(); $deleted = SoftDeletesTestUser::forceDestroy(2); $this->assertSame(1, $deleted); $users = SoftDeletesTestUser::withTrashed()->get(); $this->assertCount(1, $users); $this->assertEquals(1, $users->first()->id); $this->assertNull(SoftDeletesTestUser::find(2)); } public function testForceDestroyDeletesAlreadyDeletedRecord() { $this->createUsers(); $deleted = SoftDeletesTestUser::forceDestroy(1); $this->assertSame(1, $deleted); $users = SoftDeletesTestUser::withTrashed()->get(); $this->assertCount(1, $users); $this->assertEquals(2, $users->first()->id); $this->assertNull(SoftDeletesTestUser::find(1)); } public function testForceDestroyDeletesMultipleRecords() { $this->createUsers(); $deleted = SoftDeletesTestUser::forceDestroy([1, 2]); $this->assertSame(2, $deleted); $this->assertTrue(SoftDeletesTestUser::withTrashed()->get()->isEmpty()); } public function testForceDestroyDeletesRecordsFromCollection() { $this->createUsers(); $deleted = SoftDeletesTestUser::forceDestroy(collect([1, 2])); $this->assertSame(2, $deleted); $this->assertTrue(SoftDeletesTestUser::withTrashed()->get()->isEmpty()); } public function testForceDestroyDeletesRecordsFromEloquentCollection() { $this->createUsers(); $deleted = SoftDeletesTestUser::forceDestroy(SoftDeletesTestUser::all()); $this->assertSame(1, $deleted); $users = SoftDeletesTestUser::withTrashed()->get(); $this->assertCount(1, $users); $this->assertEquals(1, $users->first()->id); $this->assertNull(SoftDeletesTestUser::find(2)); } public function testRestoreRestoresRecords() { $this->createUsers(); $taylor = SoftDeletesTestUser::withTrashed()->find(1); $this->assertTrue($taylor->trashed()); $taylor->restore(); $users = SoftDeletesTestUser::all(); $this->assertCount(2, $users); $this->assertNull($users->find(1)->deleted_at); $this->assertNull($users->find(2)->deleted_at); } public function testRestoreDoesNotFireRestoredEventWhenSavingEventCancelsSave() { $previousDispatcher = Eloquent::getEventDispatcher(); Eloquent::setEventDispatcher(new Dispatcher); try { $this->createUsers(); $restored = false; SoftDeletesTestUser::saving(function () { return false; }); SoftDeletesTestUser::restored(function () use (&$restored) { $restored = true; }); $user = SoftDeletesTestUser::withTrashed()->find(1); $this->assertFalse($user->restore()); $this->assertFalse($restored); $this->assertNotNull(SoftDeletesTestUser::withTrashed()->find(1)->deleted_at); $this->assertNull(SoftDeletesTestUser::find(1)); } finally { SoftDeletesTestUser::flushEventListeners(); if ($previousDispatcher) { Eloquent::setEventDispatcher($previousDispatcher); } else { Eloquent::unsetEventDispatcher(); } } } public function testOnlyTrashedOnlyReturnsTrashedRecords() { $this->createUsers(); $users = SoftDeletesTestUser::onlyTrashed()->get(); $this->assertCount(1, $users); $this->assertEquals(1, $users->first()->id); } public function testOnlyWithoutTrashedOnlyReturnsTrashedRecords() { $this->createUsers(); $users = SoftDeletesTestUser::withoutTrashed()->get(); $this->assertCount(1, $users); $this->assertEquals(2, $users->first()->id); $users = SoftDeletesTestUser::withTrashed()->withoutTrashed()->get(); $this->assertCount(1, $users); $this->assertEquals(2, $users->first()->id); } public function testFirstOrNew() { $this->createUsers(); $result = SoftDeletesTestUser::firstOrNew(['email' => 'taylorotwell@gmail.com']); $this->assertNull($result->id); $result = SoftDeletesTestUser::withTrashed()->firstOrNew(['email' => 'taylorotwell@gmail.com']); $this->assertEquals(1, $result->id); } public function testFindOrNew() { $this->createUsers(); $result = SoftDeletesTestUser::findOrNew(1); $this->assertNull($result->id); $result = SoftDeletesTestUser::withTrashed()->findOrNew(1); $this->assertEquals(1, $result->id); } public function testFirstOrCreate() { $this->createUsers(); $result = SoftDeletesTestUser::withTrashed()->firstOrCreate(['email' => 'taylorotwell@gmail.com']); $this->assertSame('taylorotwell@gmail.com', $result->email); $this->assertCount(1, SoftDeletesTestUser::all()); $result = SoftDeletesTestUser::firstOrCreate(['email' => 'foo@bar.com']); $this->assertSame('foo@bar.com', $result->email); $this->assertCount(2, SoftDeletesTestUser::all()); $this->assertCount(3, SoftDeletesTestUser::withTrashed()->get()); } public function testCreateOrFirst() { $this->createUsers(); $result = SoftDeletesTestUser::withTrashed()->createOrFirst(['email' => 'taylorotwell@gmail.com']); $this->assertSame('taylorotwell@gmail.com', $result->email); $this->assertCount(1, SoftDeletesTestUser::all()); $result = SoftDeletesTestUser::createOrFirst(['email' => 'foo@bar.com']); $this->assertSame('foo@bar.com', $result->email); $this->assertCount(2, SoftDeletesTestUser::all()); $this->assertCount(3, SoftDeletesTestUser::withTrashed()->get()); } /** * @throws \Exception */ public function testUpdateModelAfterSoftDeleting() { Carbon::setTestNow($now = Carbon::now()); $this->createUsers(); /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */ $userModel = SoftDeletesTestUser::find(2); $userModel->delete(); $this->assertEquals($now->toDateTimeString(), $userModel->getOriginal('deleted_at')); $this->assertNull(SoftDeletesTestUser::find(2)); $this->assertEquals($userModel, SoftDeletesTestUser::withTrashed()->find(2)); } /** * @throws \Exception */ public function testRestoreAfterSoftDelete() { $this->createUsers(); /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */ $userModel = SoftDeletesTestUser::find(2); $userModel->delete(); $userModel->restore(); $this->assertEquals($userModel->id, SoftDeletesTestUser::find(2)->id); } /** * @throws \Exception */ public function testSoftDeleteAfterRestoring() { $this->createUsers(); /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */ $userModel = SoftDeletesTestUser::withTrashed()->find(1); $userModel->restore(); $this->assertEquals($userModel->deleted_at, SoftDeletesTestUser::find(1)->deleted_at); $this->assertEquals($userModel->getOriginal('deleted_at'), SoftDeletesTestUser::find(1)->deleted_at); $userModel->delete(); $this->assertNull(SoftDeletesTestUser::find(1)); $this->assertEquals($userModel->deleted_at, SoftDeletesTestUser::withTrashed()->find(1)->deleted_at); $this->assertEquals($userModel->getOriginal('deleted_at'), SoftDeletesTestUser::withTrashed()->find(1)->deleted_at); } public function testModifyingBeforeSoftDeletingAndRestoring() { $this->createUsers(); /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */ $userModel = SoftDeletesTestUser::find(2); $userModel->email = 'foo@bar.com'; $userModel->delete(); $userModel->restore(); $this->assertEquals($userModel->id, SoftDeletesTestUser::find(2)->id); $this->assertSame('foo@bar.com', SoftDeletesTestUser::find(2)->email); } public function testUpdateOrCreate() { $this->createUsers(); $result = SoftDeletesTestUser::updateOrCreate(['email' => 'foo@bar.com'], ['email' => 'bar@baz.com']); $this->assertSame('bar@baz.com', $result->email); $this->assertCount(2, SoftDeletesTestUser::all()); $result = SoftDeletesTestUser::withTrashed()->updateOrCreate(['email' => 'taylorotwell@gmail.com'], ['email' => 'foo@bar.com']); $this->assertSame('foo@bar.com', $result->email); $this->assertCount(2, SoftDeletesTestUser::all()); $this->assertCount(3, SoftDeletesTestUser::withTrashed()->get()); } public function testHasOneRelationshipCanBeSoftDeleted() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $abigail->address()->create(['address' => 'Laravel avenue 43']); // delete on builder $abigail->address()->delete(); $abigail = $abigail->fresh(); $this->assertNull($abigail->address); $this->assertSame('Laravel avenue 43', $abigail->address()->withTrashed()->first()->address); // restore $abigail->address()->withTrashed()->restore(); $abigail = $abigail->fresh(); $this->assertSame('Laravel avenue 43', $abigail->address->address); // delete on model $abigail->address->delete(); $abigail = $abigail->fresh(); $this->assertNull($abigail->address); $this->assertSame('Laravel avenue 43', $abigail->address()->withTrashed()->first()->address); // force delete $abigail->address()->withTrashed()->forceDelete(); $abigail = $abigail->fresh(); $this->assertNull($abigail->address); } public function testBelongsToRelationshipCanBeSoftDeleted() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $group = SoftDeletesTestGroup::create(['name' => 'admin']); $abigail->group()->associate($group); $abigail->save(); // delete on builder $abigail->group()->delete(); $abigail = $abigail->fresh(); $this->assertNull($abigail->group); $this->assertSame('admin', $abigail->group()->withTrashed()->first()->name); // restore $abigail->group()->withTrashed()->restore(); $abigail = $abigail->fresh(); $this->assertSame('admin', $abigail->group->name); // delete on model $abigail->group->delete(); $abigail = $abigail->fresh(); $this->assertNull($abigail->group); $this->assertSame('admin', $abigail->group()->withTrashed()->first()->name); // force delete $abigail->group()->withTrashed()->forceDelete(); $abigail = $abigail->fresh(); $this->assertNull($abigail->group()->withTrashed()->first()); } public function testHasManyRelationshipCanBeSoftDeleted() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $abigail->posts()->create(['title' => 'First Title']); $abigail->posts()->create(['title' => 'Second Title']); // delete on builder $abigail->posts()->where('title', 'Second Title')->delete(); $abigail = $abigail->fresh(); $this->assertCount(1, $abigail->posts); $this->assertSame('First Title', $abigail->posts->first()->title); $this->assertCount(2, $abigail->posts()->withTrashed()->get()); // restore $abigail->posts()->withTrashed()->restore(); $abigail = $abigail->fresh(); $this->assertCount(2, $abigail->posts); // force delete $abigail->posts()->where('title', 'Second Title')->forceDelete(); $abigail = $abigail->fresh(); $this->assertCount(1, $abigail->posts); $this->assertCount(1, $abigail->posts()->withTrashed()->get()); } public function testRelationToSqlAppliesSoftDelete() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $this->assertSame( 'select * from "posts" where "posts"."user_id" = ? and "posts"."user_id" is not null and "posts"."deleted_at" is null', $abigail->posts()->toSql() ); } public function testRelationExistsAndDoesntExistHonorsSoftDelete() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); // 'exists' should return true before soft delete $abigail->posts()->create(['title' => 'First Title']); $this->assertTrue($abigail->posts()->exists()); $this->assertFalse($abigail->posts()->doesntExist()); // 'exists' should return false after soft delete $abigail->posts()->first()->delete(); $this->assertFalse($abigail->posts()->exists()); $this->assertTrue($abigail->posts()->doesntExist()); // 'exists' should return true after restore $abigail->posts()->withTrashed()->restore(); $this->assertTrue($abigail->posts()->exists()); $this->assertFalse($abigail->posts()->doesntExist()); // 'exists' should return false after a force delete $abigail->posts()->first()->forceDelete(); $this->assertFalse($abigail->posts()->exists()); $this->assertTrue($abigail->posts()->doesntExist()); } public function testRelationCountHonorsSoftDelete() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); // check count before soft delete $abigail->posts()->create(['title' => 'First Title']); $abigail->posts()->create(['title' => 'Second Title']); $this->assertEquals(2, $abigail->posts()->count()); // check count after soft delete $abigail->posts()->where('title', 'Second Title')->delete(); $this->assertEquals(1, $abigail->posts()->count()); // check count after restore $abigail->posts()->withTrashed()->restore(); $this->assertEquals(2, $abigail->posts()->count()); // check count after a force delete $abigail->posts()->where('title', 'Second Title')->forceDelete(); $this->assertEquals(1, $abigail->posts()->count()); } public function testRelationAggregatesHonorsSoftDelete() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); // check aggregates before soft delete $abigail->posts()->create(['title' => 'First Title', 'priority' => 2]); $abigail->posts()->create(['title' => 'Second Title', 'priority' => 4]); $abigail->posts()->create(['title' => 'Third Title', 'priority' => 6]); $this->assertEquals(2, $abigail->posts()->min('priority')); $this->assertEquals(6, $abigail->posts()->max('priority')); $this->assertEquals(12, $abigail->posts()->sum('priority')); $this->assertEquals(4, $abigail->posts()->avg('priority')); // check aggregates after soft delete $abigail->posts()->where('title', 'First Title')->delete(); $this->assertEquals(4, $abigail->posts()->min('priority')); $this->assertEquals(6, $abigail->posts()->max('priority')); $this->assertEquals(10, $abigail->posts()->sum('priority')); $this->assertEquals(5, $abigail->posts()->avg('priority')); // check aggregates after restore $abigail->posts()->withTrashed()->restore(); $this->assertEquals(2, $abigail->posts()->min('priority')); $this->assertEquals(6, $abigail->posts()->max('priority')); $this->assertEquals(12, $abigail->posts()->sum('priority')); $this->assertEquals(4, $abigail->posts()->avg('priority')); // check aggregates after a force delete $abigail->posts()->where('title', 'Third Title')->forceDelete(); $this->assertEquals(2, $abigail->posts()->min('priority')); $this->assertEquals(4, $abigail->posts()->max('priority')); $this->assertEquals(6, $abigail->posts()->sum('priority')); $this->assertEquals(3, $abigail->posts()->avg('priority')); } public function testSoftDeleteIsAppliedToNewQuery() { $query = (new SoftDeletesTestUser)->newQuery(); $this->assertSame('select * from "users" where "users"."deleted_at" is null', $query->toSql()); } public function testSecondLevelRelationshipCanBeSoftDeleted() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post = $abigail->posts()->create(['title' => 'First Title']); $post->comments()->create(['body' => 'Comment Body']); $abigail->posts()->first()->comments()->delete(); $abigail = $abigail->fresh(); $this->assertCount(0, $abigail->posts()->first()->comments); $this->assertCount(1, $abigail->posts()->first()->comments()->withTrashed()->get()); } public function testWhereHasWithDeletedRelationship() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post = $abigail->posts()->create(['title' => 'First Title']); $users = SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->has('posts')->get(); $this->assertCount(0, $users); $users = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->has('posts')->get(); $this->assertCount(1, $users); $users = SoftDeletesTestUser::where('email', 'doesnt@exist.com')->orHas('posts')->get(); $this->assertCount(1, $users); $users = SoftDeletesTestUser::whereHas('posts', function ($query) { $query->where('title', 'First Title'); })->get(); $this->assertCount(1, $users); $users = SoftDeletesTestUser::whereHas('posts', function ($query) { $query->where('title', 'Another Title'); })->get(); $this->assertCount(0, $users); $users = SoftDeletesTestUser::where('email', 'doesnt@exist.com')->orWhereHas('posts', function ($query) { $query->where('title', 'First Title'); })->get(); $this->assertCount(1, $users); // With Post Deleted... $post->delete(); $users = SoftDeletesTestUser::has('posts')->get(); $this->assertCount(0, $users); } public function testWhereHasWithNestedDeletedRelationshipAndOnlyTrashedCondition() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post = $abigail->posts()->create(['title' => 'First Title']); $post->delete(); $users = SoftDeletesTestUser::has('posts')->get(); $this->assertCount(0, $users); $users = SoftDeletesTestUser::whereHas('posts', function ($q) { $q->onlyTrashed(); })->get(); $this->assertCount(1, $users); $users = SoftDeletesTestUser::whereHas('posts', function ($q) { $q->withTrashed(); })->get(); $this->assertCount(1, $users); } public function testWhereHasWithNestedDeletedRelationship() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post = $abigail->posts()->create(['title' => 'First Title']); $comment = $post->comments()->create(['body' => 'Comment Body']); $comment->delete(); $users = SoftDeletesTestUser::has('posts.comments')->get(); $this->assertCount(0, $users); $users = SoftDeletesTestUser::doesntHave('posts.comments')->get(); $this->assertCount(1, $users); } public function testWhereDoesntHaveWithNestedDeletedRelationship() { $this->createUsers(); $users = SoftDeletesTestUser::doesntHave('posts.comments')->get(); $this->assertCount(1, $users); } public function testWhereHasWithNestedDeletedRelationshipAndWithTrashedCondition() { $this->createUsers(); $abigail = SoftDeletesTestUserWithTrashedPosts::where('email', 'abigailotwell@gmail.com')->first(); $post = $abigail->posts()->create(['title' => 'First Title']); $post->delete(); $users = SoftDeletesTestUserWithTrashedPosts::has('posts')->get(); $this->assertCount(1, $users); } public function testWithCountWithNestedDeletedRelationshipAndOnlyTrashedCondition() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post1 = $abigail->posts()->create(['title' => 'First Title']); $post1->delete(); $abigail->posts()->create(['title' => 'Second Title']); $abigail->posts()->create(['title' => 'Third Title']); $user = SoftDeletesTestUser::withCount('posts')->orderBy('postsCount', 'desc')->first(); $this->assertEquals(2, $user->posts_count); $user = SoftDeletesTestUser::withCount(['posts' => function ($q) { $q->onlyTrashed(); }])->orderBy('postsCount', 'desc')->first(); $this->assertEquals(1, $user->posts_count); $user = SoftDeletesTestUser::withCount(['posts' => function ($q) { $q->withTrashed(); }])->orderBy('postsCount', 'desc')->first(); $this->assertEquals(3, $user->posts_count); $user = SoftDeletesTestUser::withCount(['posts' => function ($q) { $q->withTrashed()->where('title', 'First Title'); }])->orderBy('postsCount', 'desc')->first(); $this->assertEquals(1, $user->posts_count); $user = SoftDeletesTestUser::withCount(['posts' => function ($q) { $q->where('title', 'First Title'); }])->orderBy('postsCount', 'desc')->first(); $this->assertEquals(0, $user->posts_count); } public function testOrWhereWithSoftDeleteConstraint() { $this->createUsers(); $users = SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->orWhere('email', 'abigailotwell@gmail.com'); $this->assertEquals(['abigailotwell@gmail.com'], $users->pluck('email')->all()); } public function testMorphToWithTrashed() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post1 = $abigail->posts()->create(['title' => 'First Title']); $post1->comments()->create([ 'body' => 'Comment Body', 'owner_type' => SoftDeletesTestUser::class, 'owner_id' => $abigail->id, ]); $abigail->delete(); $comment = SoftDeletesTestCommentWithTrashed::with(['owner' => function ($q) { $q->withoutGlobalScope(SoftDeletingScope::class); }])->first(); $this->assertEquals($abigail->email, $comment->owner->email); $comment = SoftDeletesTestCommentWithTrashed::with(['owner' => function ($q) { $q->withTrashed(); }])->first(); $this->assertEquals($abigail->email, $comment->owner->email); $comment = TestCommentWithoutSoftDelete::with(['owner' => function ($q) { $q->withTrashed(); }])->first(); $this->assertEquals($abigail->email, $comment->owner->email); } public function testMorphToWithBadMethodCall() { $this->expectException(BadMethodCallException::class); $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post1 = $abigail->posts()->create(['title' => 'First Title']); $post1->comments()->create([ 'body' => 'Comment Body', 'owner_type' => SoftDeletesTestUser::class, 'owner_id' => $abigail->id, ]); TestCommentWithoutSoftDelete::with(['owner' => function ($q) { $q->thisMethodDoesNotExist(); }])->first(); } public function testMorphToWithConstraints() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post1 = $abigail->posts()->create(['title' => 'First Title']); $post1->comments()->create([ 'body' => 'Comment Body', 'owner_type' => SoftDeletesTestUser::class, 'owner_id' => $abigail->id, ]); $comment = SoftDeletesTestCommentWithTrashed::with(['owner' => function ($q) { $q->where('email', 'taylorotwell@gmail.com'); }])->first(); $this->assertNull($comment->owner); } public function testMorphToWithoutConstraints() { $this->createUsers(); $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first(); $post1 = $abigail->posts()->create(['title' => 'First Title']); $post1->comments()->create([ 'body' => 'Comment Body', 'owner_type' => SoftDeletesTestUser::class, 'owner_id' => $abigail->id, ]); $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first(); $this->assertEquals($abigail->email, $comment->owner->email); $abigail->delete(); $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first(); $this->assertNull($comment->owner); } public function testMorphToNonSoftDeletingModel() { $taylor = TestUserWithoutSoftDelete::create(['id' => 1, 'email' => 'taylorotwell@gmail.com']); $post1 = $taylor->posts()->create(['title' => 'First Title']); $post1->comments()->create([ 'body' => 'Comment Body', 'owner_type' => TestUserWithoutSoftDelete::class, 'owner_id' => $taylor->id, ]); $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first(); $this->assertEquals($taylor->email, $comment->owner->email); $taylor->delete(); $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first(); $this->assertNull($comment->owner); } public function testSelfReferencingRelationshipWithSoftDeletes() { // https://github.com/laravel/framework/issues/42075 [$taylor, $abigail] = $this->createUsers(); $this->assertCount(1, $abigail->self_referencing); $this->assertTrue($abigail->self_referencing->first()->is($taylor)); $this->assertCount(0, $taylor->self_referencing); $this->assertEquals(1, SoftDeletesTestUser::whereHas('self_referencing')->count()); } /** * Helpers... * * @return \Illuminate\Tests\Database\SoftDeletesTestUser[] */ protected function createUsers() { $taylor = SoftDeletesTestUser::create(['id' => 1, 'email' => 'taylorotwell@gmail.com', 'user_id' => 2]); $abigail = SoftDeletesTestUser::create(['id' => 2, 'email' => 'abigailotwell@gmail.com']); $taylor->delete(); return [$taylor, $abigail]; } /** * Get a database connection instance. * * @return \Illuminate\Database\Connection */ protected function connection() { return Eloquent::getConnectionResolver()->connection(); } /** * Get a schema builder instance. * * @return \Illuminate\Database\Schema\Builder */ protected function schema() { return $this->connection()->getSchemaBuilder(); } } /** * Eloquent Models... */ class TestUserWithoutSoftDelete extends Eloquent { protected $table = 'users'; protected $guarded = []; public function posts() { return $this->hasMany(SoftDeletesTestPost::class, 'user_id'); } } /** * Eloquent Models... */ class SoftDeletesTestUser extends Eloquent { use SoftDeletes; protected $table = 'users'; protected $guarded = []; public function self_referencing() { return $this->hasMany(SoftDeletesTestUser::class, 'user_id')->onlyTrashed(); } public function posts() { return $this->hasMany(SoftDeletesTestPost::class, 'user_id'); } public function address() { return $this->hasOne(SoftDeletesTestAddress::class, 'user_id'); } public function group() { return $this->belongsTo(SoftDeletesTestGroup::class, 'group_id'); } } class SoftDeletesTestUserWithTrashedPosts extends Eloquent { use SoftDeletes; protected $table = 'users'; protected $guarded = []; public function posts() { return $this->hasMany(SoftDeletesTestPost::class, 'user_id')->withTrashed(); } } /** * Eloquent Models... */ class SoftDeletesTestPost extends Eloquent { use SoftDeletes; protected $table = 'posts'; protected $guarded = []; public function comments() { return $this->hasMany(SoftDeletesTestComment::class, 'post_id'); } } /** * Eloquent Models... */ class TestCommentWithoutSoftDelete extends Eloquent { protected $table = 'comments'; protected $guarded = []; public function owner() { return $this->morphTo(); } } /** * Eloquent Models... */ class SoftDeletesTestComment extends Eloquent { use SoftDeletes; protected $table = 'comments'; protected $guarded = []; public function owner() { return $this->morphTo(); } } class SoftDeletesTestCommentWithTrashed extends Eloquent { use SoftDeletes; protected $table = 'comments'; protected $guarded = []; public function owner() { return $this->morphTo(); } } /** * Eloquent Models... */ class SoftDeletesTestAddress extends Eloquent { use SoftDeletes; protected $table = 'addresses'; protected $guarded = []; } /** * Eloquent Models... */ class SoftDeletesTestGroup extends Eloquent { use SoftDeletes; protected $table = 'groups'; protected $guarded = []; public function users() { $this->hasMany(SoftDeletesTestUser::class); } }