Skip to content

Commit

Permalink
[9.x] Let Multiple* exceptions hold the number of records and items f…
Browse files Browse the repository at this point in the history
…ound (#41164)

* Let Multiple* exceptions hold the number of records and items found.

* formatting

Co-authored-by: Taylor Otwell <taylor@laravel.com>
  • Loading branch information
lucasmichot and taylorotwell committed Feb 22, 2022
1 parent 7e0d9a6 commit 5ba19a2
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 14 deletions.
8 changes: 5 additions & 3 deletions src/Illuminate/Collections/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -1208,12 +1208,14 @@ public function sole($key = null, $operator = null, $value = null)

$items = $this->unless($filter == null)->filter($filter);

if ($items->isEmpty()) {
$count = $items->count();

if ($count === 0) {
throw new ItemNotFoundException;
}

if ($items->count() > 1) {
throw new MultipleItemsFoundException;
if ($count > 1) {
throw new MultipleItemsFoundException($count);
}

return $items->first();
Expand Down
31 changes: 31 additions & 0 deletions src/Illuminate/Collections/MultipleItemsFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,35 @@

class MultipleItemsFoundException extends RuntimeException
{
/**
* The number of items found.
*
* @var int
*/
public $count;

/**
* Create a new exception instance.
*
* @param int $count
* @param int $code
* @param \Throwable|null $previous
* @return void
*/
public function __construct($count, $code = 0, $previous = null)
{
$this->count = $count;

parent::__construct("$count items were found.", $code, $previous);
}

/**
* Get the number of items found.
*
* @return int
*/
public function getCount()
{
return $this->count;
}
}
8 changes: 5 additions & 3 deletions src/Illuminate/Database/Concerns/BuildsQueries.php
Original file line number Diff line number Diff line change
Expand Up @@ -309,12 +309,14 @@ public function sole($columns = ['*'])
{
$result = $this->take(2)->get($columns);

if ($result->isEmpty()) {
$count = $result->count();

if ($count === 0) {
throw new RecordsNotFoundException;
}

if ($result->count() > 1) {
throw new MultipleRecordsFoundException;
if ($count > 1) {
throw new MultipleRecordsFoundException($count);
}

return $result->first();
Expand Down
8 changes: 5 additions & 3 deletions src/Illuminate/Database/Eloquent/Relations/Relation.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,12 +171,14 @@ public function sole($columns = ['*'])
{
$result = $this->take(2)->get($columns);

if ($result->isEmpty()) {
$count = $result->count();

if ($count === 0) {
throw (new ModelNotFoundException)->setModel(get_class($this->related));
}

if ($result->count() > 1) {
throw new MultipleRecordsFoundException;
if ($count > 1) {
throw new MultipleRecordsFoundException($count);
}

return $result->first();
Expand Down
32 changes: 31 additions & 1 deletion src/Illuminate/Database/MultipleRecordsFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,35 @@

class MultipleRecordsFoundException extends RuntimeException
{
//
/**
* The number of records found.
*
* @var int
*/
public $count;

/**
* Create a new exception instance.
*
* @param int $count
* @param int $code
* @param \Throwable|null $previous
* @return void
*/
public function __construct($count, $code = 0, $previous = null)
{
$this->count = $count;

parent::__construct("$count records were found.", $code, $previous);
}

/**
* Get the number of records found.
*
* @return int
*/
public function getCount()
{
return $this->count;
}
}
2 changes: 1 addition & 1 deletion tests/Integration/Database/EloquentWhereTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public function testSoleFailsForMultipleRecords()
'address' => 'other-address',
]);

$this->expectException(MultipleRecordsFoundException::class);
$this->expectExceptionObject(new MultipleRecordsFoundException(2));

UserWhereTest::where('name', 'test-name')->sole();
}
Expand Down
2 changes: 1 addition & 1 deletion tests/Integration/Database/QueryBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function testSoleFailsForMultipleRecords()
['title' => 'Foo Post', 'content' => 'Lorem Ipsum.', 'created_at' => new Carbon('2017-11-12 13:14:15')],
]);

$this->expectException(MultipleRecordsFoundException::class);
$this->expectExceptionObject(new MultipleRecordsFoundException(2));

DB::table('posts')->where('title', 'Foo Post')->sole();
}
Expand Down
4 changes: 2 additions & 2 deletions tests/Support/SupportCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public function testSoleThrowsExceptionIfNoItemsExist($collection)
*/
public function testSoleThrowsExceptionIfMoreThanOneItemExists($collection)
{
$this->expectException(MultipleItemsFoundException::class);
$this->expectExceptionObject(new MultipleItemsFoundException(2));

$collection = new $collection([
['name' => 'foo'],
Expand Down Expand Up @@ -146,7 +146,7 @@ public function testSoleThrowsExceptionIfNoItemsExistWithCallback($collection)
*/
public function testSoleThrowsExceptionIfMoreThanOneItemExistsWithCallback($collection)
{
$this->expectException(MultipleItemsFoundException::class);
$this->expectExceptionObject(new MultipleItemsFoundException(2));

$data = new $collection(['foo', 'bar', 'bar']);

Expand Down

0 comments on commit 5ba19a2

Please sign in to comment.