Skip to content

Commit

Permalink
[8.x] Throw ModelNotFoundException for sole in Eloquent (#35902)
Browse files Browse the repository at this point in the history
* throw ModelNotFoundException for sole in Eloquent

* extend from RecordsNotFoundException
  • Loading branch information
rodrigopedra committed Jan 15, 2021
1 parent ef7171e commit ab79d0c
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 3 deletions.
24 changes: 23 additions & 1 deletion src/Illuminate/Database/Eloquent/Builder.php
Expand Up @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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.
*
Expand Down
4 changes: 2 additions & 2 deletions src/Illuminate/Database/Eloquent/ModelNotFoundException.php
Expand Up @@ -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.
Expand Down
39 changes: 39 additions & 0 deletions tests/Integration/Database/EloquentWhereTest.php
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down

0 comments on commit ab79d0c

Please sign in to comment.