From b4a604c953b098e42dd629f517679bd37e6fbcc9 Mon Sep 17 00:00:00 2001 From: Rodrigo Pedra Brum Date: Fri, 15 Jan 2021 06:47:23 -0300 Subject: [PATCH 1/2] throw ModelNotFoundException for sole in Eloquent --- src/Illuminate/Database/Eloquent/Builder.php | 24 +++++++++++- .../Database/EloquentWhereTest.php | 39 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Builder.php b/src/Illuminate/Database/Eloquent/Builder.php index d3f1f96a8c13..aa579259c1d5 100755 --- a/src/Illuminate/Database/Eloquent/Builder.php +++ b/src/Illuminate/Database/Eloquent/Builder.php @@ -11,6 +11,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Database\Query\Builder as QueryBuilder; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Pagination\Paginator; use Illuminate\Support\Arr; use Illuminate\Support\Str; @@ -25,7 +26,10 @@ */ class Builder { - use BuildsQueries, Concerns\QueriesRelationships, ExplainsQueries, ForwardsCalls; + use Concerns\QueriesRelationships, ExplainsQueries, ForwardsCalls; + use BuildsQueries { + sole as baseSole; + } /** * The base query builder instance. @@ -504,6 +508,24 @@ public function firstOr($columns = ['*'], Closure $callback = null) return $callback(); } + /** + * Execute the query and get the first result if it's the sole matching record. + * + * @param array|string $columns + * @return \Illuminate\Database\Eloquent\Model + * + * @throws \Illuminate\Database\Eloquent\ModelNotFoundException + * @throws \Illuminate\Database\MultipleRecordsFoundException + */ + public function sole($columns = ['*']) + { + try { + return $this->baseSole($columns); + } catch (RecordsNotFoundException $exception) { + throw new ModelNotFoundException($this->model); + } + } + /** * Get a single column's value from the first result of a query. * diff --git a/tests/Integration/Database/EloquentWhereTest.php b/tests/Integration/Database/EloquentWhereTest.php index c7fcc470e6f4..a400d7f76305 100644 --- a/tests/Integration/Database/EloquentWhereTest.php +++ b/tests/Integration/Database/EloquentWhereTest.php @@ -3,6 +3,8 @@ namespace Illuminate\Tests\Integration\Database; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Database\MultipleRecordsFoundException; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; @@ -91,6 +93,43 @@ public function testFirstWhere() UserWhereTest::firstWhere(['name' => 'wrong-name', 'email' => 'test-email1'], null, null, 'or')) ); } + + public function testSole() + { + $expected = UserWhereTest::create([ + 'name' => 'test-name', + 'email' => 'test-email', + 'address' => 'test-address', + ]); + + $this->assertTrue($expected->is(UserWhereTest::where('name', 'test-name')->sole())); + } + + public function testSoleFailsForMultipleRecords() + { + UserWhereTest::create([ + 'name' => 'test-name', + 'email' => 'test-email', + 'address' => 'test-address', + ]); + + UserWhereTest::create([ + 'name' => 'test-name', + 'email' => 'other-email', + 'address' => 'other-address', + ]); + + $this->expectException(MultipleRecordsFoundException::class); + + UserWhereTest::where('name', 'test-name')->sole(); + } + + public function testSoleFailsIfNoRecords() + { + $this->expectException(ModelNotFoundException::class); + + UserWhereTest::where('name', 'test-name')->sole(); + } } class UserWhereTest extends Model From 3fb2fa2c773b3a28599e7e06c1bde436eb91a1e1 Mon Sep 17 00:00:00 2001 From: Rodrigo Pedra Brum Date: Fri, 15 Jan 2021 07:20:31 -0300 Subject: [PATCH 2/2] extend from RecordsNotFoundException --- src/Illuminate/Database/Eloquent/ModelNotFoundException.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/ModelNotFoundException.php b/src/Illuminate/Database/Eloquent/ModelNotFoundException.php index 2795b934bb74..c35598bdbf46 100755 --- a/src/Illuminate/Database/Eloquent/ModelNotFoundException.php +++ b/src/Illuminate/Database/Eloquent/ModelNotFoundException.php @@ -2,10 +2,10 @@ namespace Illuminate\Database\Eloquent; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Support\Arr; -use RuntimeException; -class ModelNotFoundException extends RuntimeException +class ModelNotFoundException extends RecordsNotFoundException { /** * Name of the affected Eloquent model.