From ed96d75562ea5b6a97dc52e52484a095024c0170 Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 03:52:07 +0600 Subject: [PATCH 1/9] Introduces firstOrFail method to BuildsQueries class --- .../Database/Concerns/BuildsQueries.php | 17 +++++++++++++++++ .../Database/RecordNotFoundException.php | 10 ++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/Illuminate/Database/RecordNotFoundException.php diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index a2f43a097658..cefa77d3f07d 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -7,6 +7,7 @@ use Illuminate\Database\MultipleRecordsFoundException; use Illuminate\Database\Query\Expression; use Illuminate\Database\RecordsNotFoundException; +use Illuminate\Database\RecordNotFoundException; use Illuminate\Pagination\Cursor; use Illuminate\Pagination\CursorPaginator; use Illuminate\Pagination\LengthAwarePaginator; @@ -335,6 +336,22 @@ public function first($columns = ['*']) return $this->take(1)->get($columns)->first(); } + /** + * Execute the query and get the first result or throw an exception. + * + * @param array|string $columns + * @return \Illuminate\Database\Eloquent\Model|object|static|null + * @throws \Illuminate\Database\RecordNotFoundException + */ + public function firstOrFail($columns = ['*'], $message = null) + { + if (! is_null($result = $this->first($columns))) { + return $result; + } + + throw new RecordNotFoundException($message ?: "No record found for the given query."); + } + /** * Execute the query and get the first result if it's the sole matching record. * diff --git a/src/Illuminate/Database/RecordNotFoundException.php b/src/Illuminate/Database/RecordNotFoundException.php new file mode 100644 index 000000000000..3a717feeed24 --- /dev/null +++ b/src/Illuminate/Database/RecordNotFoundException.php @@ -0,0 +1,10 @@ + Date: Sat, 11 May 2024 11:09:39 +0600 Subject: [PATCH 2/9] Return type of newly added firstOrFail method updated --- src/Illuminate/Database/Concerns/BuildsQueries.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index cefa77d3f07d..d0225388856d 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -340,7 +340,7 @@ public function first($columns = ['*']) * Execute the query and get the first result or throw an exception. * * @param array|string $columns - * @return \Illuminate\Database\Eloquent\Model|object|static|null + * @return \Illuminate\Database\Eloquent\Model|object|static * @throws \Illuminate\Database\RecordNotFoundException */ public function firstOrFail($columns = ['*'], $message = null) From 52cee42fedbad1a666197684069c2305b892656e Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 11:10:14 +0600 Subject: [PATCH 3/9] Test cases added for firstOrFail method in DatabaseQueryBuilderTest --- tests/Database/DatabaseQueryBuilderTest.php | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index a045f41548c6..7246e8e87247 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -20,6 +20,7 @@ use Illuminate\Database\Query\Processors\MySqlProcessor; use Illuminate\Database\Query\Processors\PostgresProcessor; use Illuminate\Database\Query\Processors\Processor; +use Illuminate\Database\RecordNotFoundException; use Illuminate\Pagination\AbstractPaginator as Paginator; use Illuminate\Pagination\Cursor; use Illuminate\Pagination\CursorPaginator; @@ -2758,6 +2759,28 @@ public function testFirstMethodReturnsFirstResult() $this->assertEquals(['foo' => 'bar'], $results); } + public function testFirstOrFailMethodReturnsFirstResult() + { + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true)->andReturn([['foo' => 'bar']]); + $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [['foo' => 'bar']])->andReturnUsing(function ($query, $results) { + return $results; + }); + $results = $builder->from('users')->where('id', '=', 1)->firstOrFail(); + $this->assertEquals(['foo' => 'bar'], $results); + } + + public function testFirstOrFailMethodThrowsRecordNotFoundException() + { + $builder = $this->getBuilder(); + $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true)->andReturn([]); + + $this->expectException(RecordNotFoundException::class); + $this->expectExceptionMessage("No record found for the given query."); + + $builder->from('users')->where('id', '=', 1)->firstOrFail(); + } + public function testPluckMethodGetsCollectionOfColumnValues() { $builder = $this->getBuilder(); From f2ddb0dce5ba135b5489786a3c07f2c01c383dac Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 11:21:33 +0600 Subject: [PATCH 4/9] address Mockery exception in testFirstOrFailMethodThrowsRecordNotFoundException --- tests/Database/DatabaseQueryBuilderTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index 7246e8e87247..d7cfee96760d 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -2775,6 +2775,8 @@ public function testFirstOrFailMethodThrowsRecordNotFoundException() $builder = $this->getBuilder(); $builder->getConnection()->shouldReceive('select')->once()->with('select * from "users" where "id" = ? limit 1', [1], true)->andReturn([]); + $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [])->andReturn([]); + $this->expectException(RecordNotFoundException::class); $this->expectExceptionMessage("No record found for the given query."); From 607619404cba4e4046c056a0f2263d3ae294584e Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 11:43:15 +0600 Subject: [PATCH 5/9] StyleCI Issues Fixed --- src/Illuminate/Database/Concerns/BuildsQueries.php | 6 +++--- tests/Database/DatabaseQueryBuilderTest.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index d0225388856d..90b4360f1cb7 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -6,8 +6,8 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\MultipleRecordsFoundException; use Illuminate\Database\Query\Expression; -use Illuminate\Database\RecordsNotFoundException; use Illuminate\Database\RecordNotFoundException; +use Illuminate\Database\RecordsNotFoundException; use Illuminate\Pagination\Cursor; use Illuminate\Pagination\CursorPaginator; use Illuminate\Pagination\LengthAwarePaginator; @@ -336,7 +336,7 @@ public function first($columns = ['*']) return $this->take(1)->get($columns)->first(); } - /** + /** * Execute the query and get the first result or throw an exception. * * @param array|string $columns @@ -349,7 +349,7 @@ public function firstOrFail($columns = ['*'], $message = null) return $result; } - throw new RecordNotFoundException($message ?: "No record found for the given query."); + throw new RecordNotFoundException($message ?: 'No record found for the given query.'); } /** diff --git a/tests/Database/DatabaseQueryBuilderTest.php b/tests/Database/DatabaseQueryBuilderTest.php index d7cfee96760d..551c7ff686a3 100755 --- a/tests/Database/DatabaseQueryBuilderTest.php +++ b/tests/Database/DatabaseQueryBuilderTest.php @@ -2778,7 +2778,7 @@ public function testFirstOrFailMethodThrowsRecordNotFoundException() $builder->getProcessor()->shouldReceive('processSelect')->once()->with($builder, [])->andReturn([]); $this->expectException(RecordNotFoundException::class); - $this->expectExceptionMessage("No record found for the given query."); + $this->expectExceptionMessage('No record found for the given query.'); $builder->from('users')->where('id', '=', 1)->firstOrFail(); } From fdd9df85dc972e2b5cd3236ae2cb91c88b4884a9 Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 11:46:34 +0600 Subject: [PATCH 6/9] StyleCI Issue Fixed Again --- .../Database/Concerns/BuildsQueries.php | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 90b4360f1cb7..9ad146e5b365 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -341,11 +341,12 @@ public function first($columns = ['*']) * * @param array|string $columns * @return \Illuminate\Database\Eloquent\Model|object|static + * * @throws \Illuminate\Database\RecordNotFoundException */ public function firstOrFail($columns = ['*'], $message = null) { - if (! is_null($result = $this->first($columns))) { + if (!is_null($result = $this->first($columns))) { return $result; } @@ -389,22 +390,22 @@ public function sole($columns = ['*']) */ protected function paginateUsingCursor($perPage, $columns = ['*'], $cursorName = 'cursor', $cursor = null) { - if (! $cursor instanceof Cursor) { + if (!$cursor instanceof Cursor) { $cursor = is_string($cursor) ? Cursor::fromEncoded($cursor) : CursorPaginator::resolveCurrentCursor($cursorName, $cursor); } - $orders = $this->ensureOrderForCursorPagination(! is_null($cursor) && $cursor->pointsToPreviousItems()); + $orders = $this->ensureOrderForCursorPagination(!is_null($cursor) && $cursor->pointsToPreviousItems()); - if (! is_null($cursor)) { + if (!is_null($cursor)) { // Reset the union bindings so we can add the cursor where in the correct position... $this->setBindings([], 'union'); $addCursorConditions = function (self $builder, $previousColumn, $originalColumn, $i) use (&$addCursorConditions, $cursor, $orders) { $unionBuilders = $builder->getUnionBuilders(); - if (! is_null($previousColumn)) { + if (!is_null($previousColumn)) { $originalColumn ??= $this->getOriginalColumnNameForCursorPagination($this, $previousColumn); $builder->where( @@ -488,7 +489,7 @@ protected function getOriginalColumnNameForCursorPagination($builder, string $pa { $columns = $builder instanceof Builder ? $builder->getQuery()->getColumns() : $builder->getColumns(); - if (! is_null($columns)) { + if (!is_null($columns)) { foreach ($columns as $column) { if (($position = strripos($column, ' as ')) !== false) { $original = substr($column, 0, $position); @@ -518,7 +519,11 @@ protected function getOriginalColumnNameForCursorPagination($builder, string $pa protected function paginator($items, $total, $perPage, $currentPage, $options) { return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact( - 'items', 'total', 'perPage', 'currentPage', 'options' + 'items', + 'total', + 'perPage', + 'currentPage', + 'options' )); } @@ -534,7 +539,10 @@ protected function paginator($items, $total, $perPage, $currentPage, $options) protected function simplePaginator($items, $perPage, $currentPage, $options) { return Container::getInstance()->makeWith(Paginator::class, compact( - 'items', 'perPage', 'currentPage', 'options' + 'items', + 'perPage', + 'currentPage', + 'options' )); } @@ -550,7 +558,10 @@ protected function simplePaginator($items, $perPage, $currentPage, $options) protected function cursorPaginator($items, $perPage, $cursor, $options) { return Container::getInstance()->makeWith(CursorPaginator::class, compact( - 'items', 'perPage', 'cursor', 'options' + 'items', + 'perPage', + 'cursor', + 'options' )); } From b622f5cf30564b64df56608137cbe185260ff274 Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 11:48:27 +0600 Subject: [PATCH 7/9] Revert "StyleCI Issue Fixed Again" This reverts commit fdd9df85dc972e2b5cd3236ae2cb91c88b4884a9. --- .../Database/Concerns/BuildsQueries.php | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 9ad146e5b365..90b4360f1cb7 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -341,12 +341,11 @@ public function first($columns = ['*']) * * @param array|string $columns * @return \Illuminate\Database\Eloquent\Model|object|static - * * @throws \Illuminate\Database\RecordNotFoundException */ public function firstOrFail($columns = ['*'], $message = null) { - if (!is_null($result = $this->first($columns))) { + if (! is_null($result = $this->first($columns))) { return $result; } @@ -390,22 +389,22 @@ public function sole($columns = ['*']) */ protected function paginateUsingCursor($perPage, $columns = ['*'], $cursorName = 'cursor', $cursor = null) { - if (!$cursor instanceof Cursor) { + if (! $cursor instanceof Cursor) { $cursor = is_string($cursor) ? Cursor::fromEncoded($cursor) : CursorPaginator::resolveCurrentCursor($cursorName, $cursor); } - $orders = $this->ensureOrderForCursorPagination(!is_null($cursor) && $cursor->pointsToPreviousItems()); + $orders = $this->ensureOrderForCursorPagination(! is_null($cursor) && $cursor->pointsToPreviousItems()); - if (!is_null($cursor)) { + if (! is_null($cursor)) { // Reset the union bindings so we can add the cursor where in the correct position... $this->setBindings([], 'union'); $addCursorConditions = function (self $builder, $previousColumn, $originalColumn, $i) use (&$addCursorConditions, $cursor, $orders) { $unionBuilders = $builder->getUnionBuilders(); - if (!is_null($previousColumn)) { + if (! is_null($previousColumn)) { $originalColumn ??= $this->getOriginalColumnNameForCursorPagination($this, $previousColumn); $builder->where( @@ -489,7 +488,7 @@ protected function getOriginalColumnNameForCursorPagination($builder, string $pa { $columns = $builder instanceof Builder ? $builder->getQuery()->getColumns() : $builder->getColumns(); - if (!is_null($columns)) { + if (! is_null($columns)) { foreach ($columns as $column) { if (($position = strripos($column, ' as ')) !== false) { $original = substr($column, 0, $position); @@ -519,11 +518,7 @@ protected function getOriginalColumnNameForCursorPagination($builder, string $pa protected function paginator($items, $total, $perPage, $currentPage, $options) { return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact( - 'items', - 'total', - 'perPage', - 'currentPage', - 'options' + 'items', 'total', 'perPage', 'currentPage', 'options' )); } @@ -539,10 +534,7 @@ protected function paginator($items, $total, $perPage, $currentPage, $options) protected function simplePaginator($items, $perPage, $currentPage, $options) { return Container::getInstance()->makeWith(Paginator::class, compact( - 'items', - 'perPage', - 'currentPage', - 'options' + 'items', 'perPage', 'currentPage', 'options' )); } @@ -558,10 +550,7 @@ protected function simplePaginator($items, $perPage, $currentPage, $options) protected function cursorPaginator($items, $perPage, $cursor, $options) { return Container::getInstance()->makeWith(CursorPaginator::class, compact( - 'items', - 'perPage', - 'cursor', - 'options' + 'items', 'perPage', 'cursor', 'options' )); } From 50d551128794de66b54834be1ab0898382291d8a Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 11:48:44 +0600 Subject: [PATCH 8/9] StyleCI Issue Fixed Again --- src/Illuminate/Database/Concerns/BuildsQueries.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 90b4360f1cb7..94b134f59aee 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -341,6 +341,7 @@ public function first($columns = ['*']) * * @param array|string $columns * @return \Illuminate\Database\Eloquent\Model|object|static + * * @throws \Illuminate\Database\RecordNotFoundException */ public function firstOrFail($columns = ['*'], $message = null) From 1fabc6562dc79e45efceed33d9299cdf1ab7219d Mon Sep 17 00:00:00 2001 From: Al Nahian Date: Sat, 11 May 2024 11:49:31 +0600 Subject: [PATCH 9/9] StyleCI Issue Checked and Fixed --- src/Illuminate/Database/Concerns/BuildsQueries.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Concerns/BuildsQueries.php b/src/Illuminate/Database/Concerns/BuildsQueries.php index 94b134f59aee..f436feb2acba 100644 --- a/src/Illuminate/Database/Concerns/BuildsQueries.php +++ b/src/Illuminate/Database/Concerns/BuildsQueries.php @@ -341,7 +341,7 @@ public function first($columns = ['*']) * * @param array|string $columns * @return \Illuminate\Database\Eloquent\Model|object|static - * + * * @throws \Illuminate\Database\RecordNotFoundException */ public function firstOrFail($columns = ['*'], $message = null)