Skip to content

Commit ab79d0c

Browse files
authored
[8.x] Throw ModelNotFoundException for sole in Eloquent (#35902)
* throw ModelNotFoundException for sole in Eloquent * extend from RecordsNotFoundException
1 parent ef7171e commit ab79d0c

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

src/Illuminate/Database/Eloquent/Builder.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
1212
use Illuminate\Database\Eloquent\Relations\Relation;
1313
use Illuminate\Database\Query\Builder as QueryBuilder;
14+
use Illuminate\Database\RecordsNotFoundException;
1415
use Illuminate\Pagination\Paginator;
1516
use Illuminate\Support\Arr;
1617
use Illuminate\Support\Str;
@@ -25,7 +26,10 @@
2526
*/
2627
class Builder
2728
{
28-
use BuildsQueries, Concerns\QueriesRelationships, ExplainsQueries, ForwardsCalls;
29+
use Concerns\QueriesRelationships, ExplainsQueries, ForwardsCalls;
30+
use BuildsQueries {
31+
sole as baseSole;
32+
}
2933

3034
/**
3135
* The base query builder instance.
@@ -504,6 +508,24 @@ public function firstOr($columns = ['*'], Closure $callback = null)
504508
return $callback();
505509
}
506510

511+
/**
512+
* Execute the query and get the first result if it's the sole matching record.
513+
*
514+
* @param array|string $columns
515+
* @return \Illuminate\Database\Eloquent\Model
516+
*
517+
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
518+
* @throws \Illuminate\Database\MultipleRecordsFoundException
519+
*/
520+
public function sole($columns = ['*'])
521+
{
522+
try {
523+
return $this->baseSole($columns);
524+
} catch (RecordsNotFoundException $exception) {
525+
throw new ModelNotFoundException($this->model);
526+
}
527+
}
528+
507529
/**
508530
* Get a single column's value from the first result of a query.
509531
*

src/Illuminate/Database/Eloquent/ModelNotFoundException.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
namespace Illuminate\Database\Eloquent;
44

5+
use Illuminate\Database\RecordsNotFoundException;
56
use Illuminate\Support\Arr;
6-
use RuntimeException;
77

8-
class ModelNotFoundException extends RuntimeException
8+
class ModelNotFoundException extends RecordsNotFoundException
99
{
1010
/**
1111
* Name of the affected Eloquent model.

tests/Integration/Database/EloquentWhereTest.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Illuminate\Tests\Integration\Database;
44

55
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Database\Eloquent\ModelNotFoundException;
7+
use Illuminate\Database\MultipleRecordsFoundException;
68
use Illuminate\Database\Schema\Blueprint;
79
use Illuminate\Support\Facades\Schema;
810

@@ -91,6 +93,43 @@ public function testFirstWhere()
9193
UserWhereTest::firstWhere(['name' => 'wrong-name', 'email' => 'test-email1'], null, null, 'or'))
9294
);
9395
}
96+
97+
public function testSole()
98+
{
99+
$expected = UserWhereTest::create([
100+
'name' => 'test-name',
101+
'email' => 'test-email',
102+
'address' => 'test-address',
103+
]);
104+
105+
$this->assertTrue($expected->is(UserWhereTest::where('name', 'test-name')->sole()));
106+
}
107+
108+
public function testSoleFailsForMultipleRecords()
109+
{
110+
UserWhereTest::create([
111+
'name' => 'test-name',
112+
'email' => 'test-email',
113+
'address' => 'test-address',
114+
]);
115+
116+
UserWhereTest::create([
117+
'name' => 'test-name',
118+
'email' => 'other-email',
119+
'address' => 'other-address',
120+
]);
121+
122+
$this->expectException(MultipleRecordsFoundException::class);
123+
124+
UserWhereTest::where('name', 'test-name')->sole();
125+
}
126+
127+
public function testSoleFailsIfNoRecords()
128+
{
129+
$this->expectException(ModelNotFoundException::class);
130+
131+
UserWhereTest::where('name', 'test-name')->sole();
132+
}
94133
}
95134

96135
class UserWhereTest extends Model

0 commit comments

Comments
 (0)