DatabaseEloquentSoftDeletesIntegrationTest.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931
  1. <?php
  2. namespace Illuminate\Tests\Database;
  3. use BadMethodCallException;
  4. use Illuminate\Database\Capsule\Manager as DB;
  5. use Illuminate\Database\Eloquent\Model as Eloquent;
  6. use Illuminate\Database\Eloquent\SoftDeletes;
  7. use Illuminate\Database\Eloquent\SoftDeletingScope;
  8. use Illuminate\Database\Query\Builder;
  9. use Illuminate\Pagination\CursorPaginator;
  10. use Illuminate\Pagination\Paginator;
  11. use Illuminate\Support\Carbon;
  12. use Mockery;
  13. use PHPUnit\Framework\TestCase;
  14. class DatabaseEloquentSoftDeletesIntegrationTest extends TestCase
  15. {
  16. protected function setUp(): void
  17. {
  18. Carbon::setTestNow(Carbon::now());
  19. $db = new DB;
  20. $db->addConnection([
  21. 'driver' => 'sqlite',
  22. 'database' => ':memory:',
  23. ]);
  24. $db->bootEloquent();
  25. $db->setAsGlobal();
  26. $this->createSchema();
  27. }
  28. /**
  29. * Setup the database schema.
  30. *
  31. * @return void
  32. */
  33. public function createSchema()
  34. {
  35. $this->schema()->create('users', function ($table) {
  36. $table->increments('id');
  37. $table->integer('group_id')->nullable();
  38. $table->string('email')->unique();
  39. $table->timestamps();
  40. $table->softDeletes();
  41. });
  42. $this->schema()->create('posts', function ($table) {
  43. $table->increments('id');
  44. $table->integer('user_id');
  45. $table->string('title');
  46. $table->timestamps();
  47. $table->softDeletes();
  48. });
  49. $this->schema()->create('comments', function ($table) {
  50. $table->increments('id');
  51. $table->integer('owner_id')->nullable();
  52. $table->string('owner_type')->nullable();
  53. $table->integer('post_id');
  54. $table->string('body');
  55. $table->timestamps();
  56. $table->softDeletes();
  57. });
  58. $this->schema()->create('addresses', function ($table) {
  59. $table->increments('id');
  60. $table->integer('user_id');
  61. $table->string('address');
  62. $table->timestamps();
  63. $table->softDeletes();
  64. });
  65. $this->schema()->create('groups', function ($table) {
  66. $table->increments('id');
  67. $table->string('name');
  68. $table->timestamps();
  69. $table->softDeletes();
  70. });
  71. }
  72. /**
  73. * Tear down the database schema.
  74. *
  75. * @return void
  76. */
  77. protected function tearDown(): void
  78. {
  79. Carbon::setTestNow(null);
  80. $this->schema()->drop('users');
  81. $this->schema()->drop('posts');
  82. $this->schema()->drop('comments');
  83. }
  84. /**
  85. * Tests...
  86. */
  87. public function testSoftDeletesAreNotRetrieved()
  88. {
  89. $this->createUsers();
  90. $users = SoftDeletesTestUser::all();
  91. $this->assertCount(1, $users);
  92. $this->assertEquals(2, $users->first()->id);
  93. $this->assertNull(SoftDeletesTestUser::find(1));
  94. }
  95. public function testSoftDeletesAreNotRetrievedFromBaseQuery()
  96. {
  97. $this->createUsers();
  98. $query = SoftDeletesTestUser::query()->toBase();
  99. $this->assertInstanceOf(Builder::class, $query);
  100. $this->assertCount(1, $query->get());
  101. }
  102. public function testSoftDeletesAreNotRetrievedFromBuilderHelpers()
  103. {
  104. $this->createUsers();
  105. $count = 0;
  106. $query = SoftDeletesTestUser::query();
  107. $query->chunk(2, function ($user) use (&$count) {
  108. $count += count($user);
  109. });
  110. $this->assertEquals(1, $count);
  111. $query = SoftDeletesTestUser::query();
  112. $this->assertCount(1, $query->pluck('email')->all());
  113. Paginator::currentPageResolver(function () {
  114. return 1;
  115. });
  116. CursorPaginator::currentCursorResolver(function () {
  117. return null;
  118. });
  119. $query = SoftDeletesTestUser::query();
  120. $this->assertCount(1, $query->paginate(2)->all());
  121. $query = SoftDeletesTestUser::query();
  122. $this->assertCount(1, $query->simplePaginate(2)->all());
  123. $query = SoftDeletesTestUser::query();
  124. $this->assertCount(1, $query->cursorPaginate(2)->all());
  125. $this->assertEquals(0, SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->increment('id'));
  126. $this->assertEquals(0, SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->decrement('id'));
  127. }
  128. public function testWithTrashedReturnsAllRecords()
  129. {
  130. $this->createUsers();
  131. $this->assertCount(2, SoftDeletesTestUser::withTrashed()->get());
  132. $this->assertInstanceOf(Eloquent::class, SoftDeletesTestUser::withTrashed()->find(1));
  133. }
  134. public function testWithTrashedAcceptsAnArgument()
  135. {
  136. $this->createUsers();
  137. $this->assertCount(1, SoftDeletesTestUser::withTrashed(false)->get());
  138. $this->assertCount(2, SoftDeletesTestUser::withTrashed(true)->get());
  139. }
  140. public function testDeleteSetsDeletedColumn()
  141. {
  142. $this->createUsers();
  143. $this->assertInstanceOf(Carbon::class, SoftDeletesTestUser::withTrashed()->find(1)->deleted_at);
  144. $this->assertNull(SoftDeletesTestUser::find(2)->deleted_at);
  145. }
  146. public function testForceDeleteActuallyDeletesRecords()
  147. {
  148. $this->createUsers();
  149. SoftDeletesTestUser::find(2)->forceDelete();
  150. $users = SoftDeletesTestUser::withTrashed()->get();
  151. $this->assertCount(1, $users);
  152. $this->assertEquals(1, $users->first()->id);
  153. }
  154. public function testForceDeleteUpdateExistsProperty()
  155. {
  156. $this->createUsers();
  157. $user = SoftDeletesTestUser::find(2);
  158. $this->assertTrue($user->exists);
  159. $user->forceDelete();
  160. $this->assertFalse($user->exists);
  161. }
  162. public function testForceDeleteDoesntUpdateExistsPropertyIfFailed()
  163. {
  164. $user = new class() extends SoftDeletesTestUser
  165. {
  166. public $exists = true;
  167. public function newModelQuery()
  168. {
  169. return Mockery::spy(parent::newModelQuery(), function (Mockery\MockInterface $mock) {
  170. $mock->shouldReceive('forceDelete')->andThrow(new \Exception());
  171. });
  172. }
  173. };
  174. $this->assertTrue($user->exists);
  175. try {
  176. $user->forceDelete();
  177. } catch (\Exception $exception) {
  178. }
  179. $this->assertTrue($user->exists);
  180. }
  181. public function testRestoreRestoresRecords()
  182. {
  183. $this->createUsers();
  184. $taylor = SoftDeletesTestUser::withTrashed()->find(1);
  185. $this->assertTrue($taylor->trashed());
  186. $taylor->restore();
  187. $users = SoftDeletesTestUser::all();
  188. $this->assertCount(2, $users);
  189. $this->assertNull($users->find(1)->deleted_at);
  190. $this->assertNull($users->find(2)->deleted_at);
  191. }
  192. public function testOnlyTrashedOnlyReturnsTrashedRecords()
  193. {
  194. $this->createUsers();
  195. $users = SoftDeletesTestUser::onlyTrashed()->get();
  196. $this->assertCount(1, $users);
  197. $this->assertEquals(1, $users->first()->id);
  198. }
  199. public function testOnlyWithoutTrashedOnlyReturnsTrashedRecords()
  200. {
  201. $this->createUsers();
  202. $users = SoftDeletesTestUser::withoutTrashed()->get();
  203. $this->assertCount(1, $users);
  204. $this->assertEquals(2, $users->first()->id);
  205. $users = SoftDeletesTestUser::withTrashed()->withoutTrashed()->get();
  206. $this->assertCount(1, $users);
  207. $this->assertEquals(2, $users->first()->id);
  208. }
  209. public function testFirstOrNew()
  210. {
  211. $this->createUsers();
  212. $result = SoftDeletesTestUser::firstOrNew(['email' => 'taylorotwell@gmail.com']);
  213. $this->assertNull($result->id);
  214. $result = SoftDeletesTestUser::withTrashed()->firstOrNew(['email' => 'taylorotwell@gmail.com']);
  215. $this->assertEquals(1, $result->id);
  216. }
  217. public function testFindOrNew()
  218. {
  219. $this->createUsers();
  220. $result = SoftDeletesTestUser::findOrNew(1);
  221. $this->assertNull($result->id);
  222. $result = SoftDeletesTestUser::withTrashed()->findOrNew(1);
  223. $this->assertEquals(1, $result->id);
  224. }
  225. public function testFirstOrCreate()
  226. {
  227. $this->createUsers();
  228. $result = SoftDeletesTestUser::withTrashed()->firstOrCreate(['email' => 'taylorotwell@gmail.com']);
  229. $this->assertSame('taylorotwell@gmail.com', $result->email);
  230. $this->assertCount(1, SoftDeletesTestUser::all());
  231. $result = SoftDeletesTestUser::firstOrCreate(['email' => 'foo@bar.com']);
  232. $this->assertSame('foo@bar.com', $result->email);
  233. $this->assertCount(2, SoftDeletesTestUser::all());
  234. $this->assertCount(3, SoftDeletesTestUser::withTrashed()->get());
  235. }
  236. /**
  237. * @throws \Exception
  238. */
  239. public function testUpdateModelAfterSoftDeleting()
  240. {
  241. $now = Carbon::now();
  242. $this->createUsers();
  243. /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */
  244. $userModel = SoftDeletesTestUser::find(2);
  245. $userModel->delete();
  246. $this->assertEquals($now->toDateTimeString(), $userModel->getOriginal('deleted_at'));
  247. $this->assertNull(SoftDeletesTestUser::find(2));
  248. $this->assertEquals($userModel, SoftDeletesTestUser::withTrashed()->find(2));
  249. }
  250. /**
  251. * @throws \Exception
  252. */
  253. public function testRestoreAfterSoftDelete()
  254. {
  255. $this->createUsers();
  256. /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */
  257. $userModel = SoftDeletesTestUser::find(2);
  258. $userModel->delete();
  259. $userModel->restore();
  260. $this->assertEquals($userModel->id, SoftDeletesTestUser::find(2)->id);
  261. }
  262. /**
  263. * @throws \Exception
  264. */
  265. public function testSoftDeleteAfterRestoring()
  266. {
  267. $this->createUsers();
  268. /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */
  269. $userModel = SoftDeletesTestUser::withTrashed()->find(1);
  270. $userModel->restore();
  271. $this->assertEquals($userModel->deleted_at, SoftDeletesTestUser::find(1)->deleted_at);
  272. $this->assertEquals($userModel->getOriginal('deleted_at'), SoftDeletesTestUser::find(1)->deleted_at);
  273. $userModel->delete();
  274. $this->assertNull(SoftDeletesTestUser::find(1));
  275. $this->assertEquals($userModel->deleted_at, SoftDeletesTestUser::withTrashed()->find(1)->deleted_at);
  276. $this->assertEquals($userModel->getOriginal('deleted_at'), SoftDeletesTestUser::withTrashed()->find(1)->deleted_at);
  277. }
  278. public function testModifyingBeforeSoftDeletingAndRestoring()
  279. {
  280. $this->createUsers();
  281. /** @var \Illuminate\Tests\Database\SoftDeletesTestUser $userModel */
  282. $userModel = SoftDeletesTestUser::find(2);
  283. $userModel->email = 'foo@bar.com';
  284. $userModel->delete();
  285. $userModel->restore();
  286. $this->assertEquals($userModel->id, SoftDeletesTestUser::find(2)->id);
  287. $this->assertSame('foo@bar.com', SoftDeletesTestUser::find(2)->email);
  288. }
  289. public function testUpdateOrCreate()
  290. {
  291. $this->createUsers();
  292. $result = SoftDeletesTestUser::updateOrCreate(['email' => 'foo@bar.com'], ['email' => 'bar@baz.com']);
  293. $this->assertSame('bar@baz.com', $result->email);
  294. $this->assertCount(2, SoftDeletesTestUser::all());
  295. $result = SoftDeletesTestUser::withTrashed()->updateOrCreate(['email' => 'taylorotwell@gmail.com'], ['email' => 'foo@bar.com']);
  296. $this->assertSame('foo@bar.com', $result->email);
  297. $this->assertCount(2, SoftDeletesTestUser::all());
  298. $this->assertCount(3, SoftDeletesTestUser::withTrashed()->get());
  299. }
  300. public function testHasOneRelationshipCanBeSoftDeleted()
  301. {
  302. $this->createUsers();
  303. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  304. $abigail->address()->create(['address' => 'Laravel avenue 43']);
  305. // delete on builder
  306. $abigail->address()->delete();
  307. $abigail = $abigail->fresh();
  308. $this->assertNull($abigail->address);
  309. $this->assertSame('Laravel avenue 43', $abigail->address()->withTrashed()->first()->address);
  310. // restore
  311. $abigail->address()->withTrashed()->restore();
  312. $abigail = $abigail->fresh();
  313. $this->assertSame('Laravel avenue 43', $abigail->address->address);
  314. // delete on model
  315. $abigail->address->delete();
  316. $abigail = $abigail->fresh();
  317. $this->assertNull($abigail->address);
  318. $this->assertSame('Laravel avenue 43', $abigail->address()->withTrashed()->first()->address);
  319. // force delete
  320. $abigail->address()->withTrashed()->forceDelete();
  321. $abigail = $abigail->fresh();
  322. $this->assertNull($abigail->address);
  323. }
  324. public function testBelongsToRelationshipCanBeSoftDeleted()
  325. {
  326. $this->createUsers();
  327. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  328. $group = SoftDeletesTestGroup::create(['name' => 'admin']);
  329. $abigail->group()->associate($group);
  330. $abigail->save();
  331. // delete on builder
  332. $abigail->group()->delete();
  333. $abigail = $abigail->fresh();
  334. $this->assertNull($abigail->group);
  335. $this->assertSame('admin', $abigail->group()->withTrashed()->first()->name);
  336. // restore
  337. $abigail->group()->withTrashed()->restore();
  338. $abigail = $abigail->fresh();
  339. $this->assertSame('admin', $abigail->group->name);
  340. // delete on model
  341. $abigail->group->delete();
  342. $abigail = $abigail->fresh();
  343. $this->assertNull($abigail->group);
  344. $this->assertSame('admin', $abigail->group()->withTrashed()->first()->name);
  345. // force delete
  346. $abigail->group()->withTrashed()->forceDelete();
  347. $abigail = $abigail->fresh();
  348. $this->assertNull($abigail->group()->withTrashed()->first());
  349. }
  350. public function testHasManyRelationshipCanBeSoftDeleted()
  351. {
  352. $this->createUsers();
  353. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  354. $abigail->posts()->create(['title' => 'First Title']);
  355. $abigail->posts()->create(['title' => 'Second Title']);
  356. // delete on builder
  357. $abigail->posts()->where('title', 'Second Title')->delete();
  358. $abigail = $abigail->fresh();
  359. $this->assertCount(1, $abigail->posts);
  360. $this->assertSame('First Title', $abigail->posts->first()->title);
  361. $this->assertCount(2, $abigail->posts()->withTrashed()->get());
  362. // restore
  363. $abigail->posts()->withTrashed()->restore();
  364. $abigail = $abigail->fresh();
  365. $this->assertCount(2, $abigail->posts);
  366. // force delete
  367. $abigail->posts()->where('title', 'Second Title')->forceDelete();
  368. $abigail = $abigail->fresh();
  369. $this->assertCount(1, $abigail->posts);
  370. $this->assertCount(1, $abigail->posts()->withTrashed()->get());
  371. }
  372. public function testSecondLevelRelationshipCanBeSoftDeleted()
  373. {
  374. $this->createUsers();
  375. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  376. $post = $abigail->posts()->create(['title' => 'First Title']);
  377. $post->comments()->create(['body' => 'Comment Body']);
  378. $abigail->posts()->first()->comments()->delete();
  379. $abigail = $abigail->fresh();
  380. $this->assertCount(0, $abigail->posts()->first()->comments);
  381. $this->assertCount(1, $abigail->posts()->first()->comments()->withTrashed()->get());
  382. }
  383. public function testWhereHasWithDeletedRelationship()
  384. {
  385. $this->createUsers();
  386. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  387. $post = $abigail->posts()->create(['title' => 'First Title']);
  388. $users = SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->has('posts')->get();
  389. $this->assertCount(0, $users);
  390. $users = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->has('posts')->get();
  391. $this->assertCount(1, $users);
  392. $users = SoftDeletesTestUser::where('email', 'doesnt@exist.com')->orHas('posts')->get();
  393. $this->assertCount(1, $users);
  394. $users = SoftDeletesTestUser::whereHas('posts', function ($query) {
  395. $query->where('title', 'First Title');
  396. })->get();
  397. $this->assertCount(1, $users);
  398. $users = SoftDeletesTestUser::whereHas('posts', function ($query) {
  399. $query->where('title', 'Another Title');
  400. })->get();
  401. $this->assertCount(0, $users);
  402. $users = SoftDeletesTestUser::where('email', 'doesnt@exist.com')->orWhereHas('posts', function ($query) {
  403. $query->where('title', 'First Title');
  404. })->get();
  405. $this->assertCount(1, $users);
  406. // With Post Deleted...
  407. $post->delete();
  408. $users = SoftDeletesTestUser::has('posts')->get();
  409. $this->assertCount(0, $users);
  410. }
  411. public function testWhereHasWithNestedDeletedRelationshipAndOnlyTrashedCondition()
  412. {
  413. $this->createUsers();
  414. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  415. $post = $abigail->posts()->create(['title' => 'First Title']);
  416. $post->delete();
  417. $users = SoftDeletesTestUser::has('posts')->get();
  418. $this->assertCount(0, $users);
  419. $users = SoftDeletesTestUser::whereHas('posts', function ($q) {
  420. $q->onlyTrashed();
  421. })->get();
  422. $this->assertCount(1, $users);
  423. $users = SoftDeletesTestUser::whereHas('posts', function ($q) {
  424. $q->withTrashed();
  425. })->get();
  426. $this->assertCount(1, $users);
  427. }
  428. public function testWhereHasWithNestedDeletedRelationship()
  429. {
  430. $this->createUsers();
  431. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  432. $post = $abigail->posts()->create(['title' => 'First Title']);
  433. $comment = $post->comments()->create(['body' => 'Comment Body']);
  434. $comment->delete();
  435. $users = SoftDeletesTestUser::has('posts.comments')->get();
  436. $this->assertCount(0, $users);
  437. $users = SoftDeletesTestUser::doesntHave('posts.comments')->get();
  438. $this->assertCount(1, $users);
  439. }
  440. public function testWhereDoesntHaveWithNestedDeletedRelationship()
  441. {
  442. $this->createUsers();
  443. $users = SoftDeletesTestUser::doesntHave('posts.comments')->get();
  444. $this->assertCount(1, $users);
  445. }
  446. public function testWhereHasWithNestedDeletedRelationshipAndWithTrashedCondition()
  447. {
  448. $this->createUsers();
  449. $abigail = SoftDeletesTestUserWithTrashedPosts::where('email', 'abigailotwell@gmail.com')->first();
  450. $post = $abigail->posts()->create(['title' => 'First Title']);
  451. $post->delete();
  452. $users = SoftDeletesTestUserWithTrashedPosts::has('posts')->get();
  453. $this->assertCount(1, $users);
  454. }
  455. public function testWithCountWithNestedDeletedRelationshipAndOnlyTrashedCondition()
  456. {
  457. $this->createUsers();
  458. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  459. $post1 = $abigail->posts()->create(['title' => 'First Title']);
  460. $post1->delete();
  461. $abigail->posts()->create(['title' => 'Second Title']);
  462. $abigail->posts()->create(['title' => 'Third Title']);
  463. $user = SoftDeletesTestUser::withCount('posts')->orderBy('postsCount', 'desc')->first();
  464. $this->assertEquals(2, $user->posts_count);
  465. $user = SoftDeletesTestUser::withCount(['posts' => function ($q) {
  466. $q->onlyTrashed();
  467. }])->orderBy('postsCount', 'desc')->first();
  468. $this->assertEquals(1, $user->posts_count);
  469. $user = SoftDeletesTestUser::withCount(['posts' => function ($q) {
  470. $q->withTrashed();
  471. }])->orderBy('postsCount', 'desc')->first();
  472. $this->assertEquals(3, $user->posts_count);
  473. $user = SoftDeletesTestUser::withCount(['posts' => function ($q) {
  474. $q->withTrashed()->where('title', 'First Title');
  475. }])->orderBy('postsCount', 'desc')->first();
  476. $this->assertEquals(1, $user->posts_count);
  477. $user = SoftDeletesTestUser::withCount(['posts' => function ($q) {
  478. $q->where('title', 'First Title');
  479. }])->orderBy('postsCount', 'desc')->first();
  480. $this->assertEquals(0, $user->posts_count);
  481. }
  482. public function testOrWhereWithSoftDeleteConstraint()
  483. {
  484. $this->createUsers();
  485. $users = SoftDeletesTestUser::where('email', 'taylorotwell@gmail.com')->orWhere('email', 'abigailotwell@gmail.com');
  486. $this->assertEquals(['abigailotwell@gmail.com'], $users->pluck('email')->all());
  487. }
  488. public function testMorphToWithTrashed()
  489. {
  490. $this->createUsers();
  491. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  492. $post1 = $abigail->posts()->create(['title' => 'First Title']);
  493. $post1->comments()->create([
  494. 'body' => 'Comment Body',
  495. 'owner_type' => SoftDeletesTestUser::class,
  496. 'owner_id' => $abigail->id,
  497. ]);
  498. $abigail->delete();
  499. $comment = SoftDeletesTestCommentWithTrashed::with(['owner' => function ($q) {
  500. $q->withoutGlobalScope(SoftDeletingScope::class);
  501. }])->first();
  502. $this->assertEquals($abigail->email, $comment->owner->email);
  503. $comment = SoftDeletesTestCommentWithTrashed::with(['owner' => function ($q) {
  504. $q->withTrashed();
  505. }])->first();
  506. $this->assertEquals($abigail->email, $comment->owner->email);
  507. $comment = TestCommentWithoutSoftDelete::with(['owner' => function ($q) {
  508. $q->withTrashed();
  509. }])->first();
  510. $this->assertEquals($abigail->email, $comment->owner->email);
  511. }
  512. public function testMorphToWithBadMethodCall()
  513. {
  514. $this->expectException(BadMethodCallException::class);
  515. $this->createUsers();
  516. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  517. $post1 = $abigail->posts()->create(['title' => 'First Title']);
  518. $post1->comments()->create([
  519. 'body' => 'Comment Body',
  520. 'owner_type' => SoftDeletesTestUser::class,
  521. 'owner_id' => $abigail->id,
  522. ]);
  523. TestCommentWithoutSoftDelete::with(['owner' => function ($q) {
  524. $q->thisMethodDoesNotExist();
  525. }])->first();
  526. }
  527. public function testMorphToWithConstraints()
  528. {
  529. $this->createUsers();
  530. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  531. $post1 = $abigail->posts()->create(['title' => 'First Title']);
  532. $post1->comments()->create([
  533. 'body' => 'Comment Body',
  534. 'owner_type' => SoftDeletesTestUser::class,
  535. 'owner_id' => $abigail->id,
  536. ]);
  537. $comment = SoftDeletesTestCommentWithTrashed::with(['owner' => function ($q) {
  538. $q->where('email', 'taylorotwell@gmail.com');
  539. }])->first();
  540. $this->assertNull($comment->owner);
  541. }
  542. public function testMorphToWithoutConstraints()
  543. {
  544. $this->createUsers();
  545. $abigail = SoftDeletesTestUser::where('email', 'abigailotwell@gmail.com')->first();
  546. $post1 = $abigail->posts()->create(['title' => 'First Title']);
  547. $post1->comments()->create([
  548. 'body' => 'Comment Body',
  549. 'owner_type' => SoftDeletesTestUser::class,
  550. 'owner_id' => $abigail->id,
  551. ]);
  552. $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first();
  553. $this->assertEquals($abigail->email, $comment->owner->email);
  554. $abigail->delete();
  555. $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first();
  556. $this->assertNull($comment->owner);
  557. }
  558. public function testMorphToNonSoftDeletingModel()
  559. {
  560. $taylor = TestUserWithoutSoftDelete::create(['id' => 1, 'email' => 'taylorotwell@gmail.com']);
  561. $post1 = $taylor->posts()->create(['title' => 'First Title']);
  562. $post1->comments()->create([
  563. 'body' => 'Comment Body',
  564. 'owner_type' => TestUserWithoutSoftDelete::class,
  565. 'owner_id' => $taylor->id,
  566. ]);
  567. $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first();
  568. $this->assertEquals($taylor->email, $comment->owner->email);
  569. $taylor->delete();
  570. $comment = SoftDeletesTestCommentWithTrashed::with('owner')->first();
  571. $this->assertNull($comment->owner);
  572. }
  573. /**
  574. * Helpers...
  575. */
  576. protected function createUsers()
  577. {
  578. $taylor = SoftDeletesTestUser::create(['id' => 1, 'email' => 'taylorotwell@gmail.com']);
  579. SoftDeletesTestUser::create(['id' => 2, 'email' => 'abigailotwell@gmail.com']);
  580. $taylor->delete();
  581. }
  582. /**
  583. * Get a database connection instance.
  584. *
  585. * @return \Illuminate\Database\Connection
  586. */
  587. protected function connection()
  588. {
  589. return Eloquent::getConnectionResolver()->connection();
  590. }
  591. /**
  592. * Get a schema builder instance.
  593. *
  594. * @return \Illuminate\Database\Schema\Builder
  595. */
  596. protected function schema()
  597. {
  598. return $this->connection()->getSchemaBuilder();
  599. }
  600. }
  601. /**
  602. * Eloquent Models...
  603. */
  604. class TestUserWithoutSoftDelete extends Eloquent
  605. {
  606. protected $table = 'users';
  607. protected $guarded = [];
  608. public function posts()
  609. {
  610. return $this->hasMany(SoftDeletesTestPost::class, 'user_id');
  611. }
  612. }
  613. /**
  614. * Eloquent Models...
  615. */
  616. class SoftDeletesTestUser extends Eloquent
  617. {
  618. use SoftDeletes;
  619. protected $table = 'users';
  620. protected $guarded = [];
  621. public function posts()
  622. {
  623. return $this->hasMany(SoftDeletesTestPost::class, 'user_id');
  624. }
  625. public function address()
  626. {
  627. return $this->hasOne(SoftDeletesTestAddress::class, 'user_id');
  628. }
  629. public function group()
  630. {
  631. return $this->belongsTo(SoftDeletesTestGroup::class, 'group_id');
  632. }
  633. }
  634. class SoftDeletesTestUserWithTrashedPosts extends Eloquent
  635. {
  636. use SoftDeletes;
  637. protected $table = 'users';
  638. protected $guarded = [];
  639. public function posts()
  640. {
  641. return $this->hasMany(SoftDeletesTestPost::class, 'user_id')->withTrashed();
  642. }
  643. }
  644. /**
  645. * Eloquent Models...
  646. */
  647. class SoftDeletesTestPost extends Eloquent
  648. {
  649. use SoftDeletes;
  650. protected $table = 'posts';
  651. protected $guarded = [];
  652. public function comments()
  653. {
  654. return $this->hasMany(SoftDeletesTestComment::class, 'post_id');
  655. }
  656. }
  657. /**
  658. * Eloquent Models...
  659. */
  660. class TestCommentWithoutSoftDelete extends Eloquent
  661. {
  662. protected $table = 'comments';
  663. protected $guarded = [];
  664. public function owner()
  665. {
  666. return $this->morphTo();
  667. }
  668. }
  669. /**
  670. * Eloquent Models...
  671. */
  672. class SoftDeletesTestComment extends Eloquent
  673. {
  674. use SoftDeletes;
  675. protected $table = 'comments';
  676. protected $guarded = [];
  677. public function owner()
  678. {
  679. return $this->morphTo();
  680. }
  681. }
  682. class SoftDeletesTestCommentWithTrashed extends Eloquent
  683. {
  684. use SoftDeletes;
  685. protected $table = 'comments';
  686. protected $guarded = [];
  687. public function owner()
  688. {
  689. return $this->morphTo();
  690. }
  691. }
  692. /**
  693. * Eloquent Models...
  694. */
  695. class SoftDeletesTestAddress extends Eloquent
  696. {
  697. use SoftDeletes;
  698. protected $table = 'addresses';
  699. protected $guarded = [];
  700. }
  701. /**
  702. * Eloquent Models...
  703. */
  704. class SoftDeletesTestGroup extends Eloquent
  705. {
  706. use SoftDeletes;
  707. protected $table = 'groups';
  708. protected $guarded = [];
  709. public function users()
  710. {
  711. $this->hasMany(SoftDeletesTestUser::class);
  712. }
  713. }