New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
[8.x] Added sole() and soleWhere() methods for Collections #37034
Changes from 12 commits
1aef429
af6270d
d9c21db
034bad1
5465ded
04a1df1
d6a023e
534bb57
d8cd628
483e43b
4e76b91
c0a82d8
3c4f386
2d3b63c
9c42ab1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
namespace Illuminate\Collections; | ||
|
||
use RuntimeException; | ||
|
||
class ItemNotFoundException extends RuntimeException | ||
{ | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1010,6 +1010,26 @@ public function split($numberOfGroups) | |
return $this->passthru('split', func_get_args()); | ||
} | ||
|
||
/** | ||
* Get the first item in the collection, but only if exactly | ||
* item exists. Otherwise, throw an exception. | ||
* | ||
* @param callable|null $callback | ||
* @return mixed | ||
* | ||
* @throws \Illuminate\Collections\ItemNotFoundException | ||
* @throws \Illuminate\Collections\MultipleItemsFoundException | ||
*/ | ||
public function sole(callable $callback = null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This implementation is way more complex than it needs to be. Something like this (not tested) should suffice: public function sole(callable $callback = null)
{
return $this
->when($callback)
->filter($callback)
->take(2)
->collect()
->sole();
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do agree that it's more complex. I was looking at some of the existing code for things like the |
||
{ | ||
return $this | ||
->when($callback) | ||
->filter($callback) | ||
->take(2) | ||
->collect() | ||
->sole(); | ||
} | ||
|
||
/** | ||
* Chunk the collection into chunks of the given size. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?php | ||
|
||
namespace Illuminate\Collections; | ||
|
||
use RuntimeException; | ||
|
||
class MultipleItemsFoundException extends RuntimeException | ||
{ | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ | |
use ArrayObject; | ||
use CachingIterator; | ||
use Exception; | ||
use Illuminate\Collections\ItemNotFoundException; | ||
use Illuminate\Collections\MultipleItemsFoundException; | ||
use Illuminate\Contracts\Support\Arrayable; | ||
use Illuminate\Contracts\Support\Jsonable; | ||
use Illuminate\Support\Collection; | ||
|
@@ -66,6 +68,90 @@ public function testFirstWithDefaultAndWithoutCallback($collection) | |
$this->assertSame('default', $result); | ||
} | ||
|
||
/** | ||
* @dataProvider collectionClassProvider | ||
*/ | ||
public function testSoleReturnsFirstItemInCollectionIfOnlyOneExists($collection) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please also add tests in SupportLazyCollectionIsLazyTest.php ensuring this method is lazy. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah sure, I didn't realise those tests were there, so I'll add some to it |
||
{ | ||
$collection = new $collection([ | ||
['name' => 'foo'], | ||
['name' => 'bar'], | ||
]); | ||
|
||
$this->assertSame(['name' => 'foo'], $collection->where('name', 'foo')->sole()); | ||
} | ||
|
||
/** | ||
* @dataProvider collectionClassProvider | ||
*/ | ||
public function testSoleThrowsExceptionIfNoItemsExists($collection) | ||
{ | ||
$this->expectException(ItemNotFoundException::class); | ||
|
||
$collection = new $collection([ | ||
['name' => 'foo'], | ||
['name' => 'bar'], | ||
]); | ||
|
||
$collection->where('name', 'INVALID')->sole(); | ||
} | ||
|
||
/** | ||
* @dataProvider collectionClassProvider | ||
*/ | ||
public function testSoleThrowsExceptionIfMoreThanOneItemExists($collection) | ||
{ | ||
$this->expectException(MultipleItemsFoundException::class); | ||
|
||
$collection = new $collection([ | ||
['name' => 'foo'], | ||
['name' => 'foo'], | ||
['name' => 'bar'], | ||
]); | ||
|
||
$collection->where('name', 'foo')->sole(); | ||
} | ||
|
||
/** | ||
* @dataProvider collectionClassProvider | ||
*/ | ||
public function testSoleReturnsFirstItemInCollectionIfOnlyOneExistsWithCallback($collection) | ||
{ | ||
$data = new $collection(['foo', 'bar', 'baz']); | ||
$result = $data->sole(function ($value) { | ||
return $value === 'bar'; | ||
}); | ||
$this->assertSame('bar', $result); | ||
} | ||
|
||
/** | ||
* @dataProvider collectionClassProvider | ||
*/ | ||
public function testSoleThrowsExceptionIfNoItemsExistsWithCallback($collection) | ||
{ | ||
$this->expectException(ItemNotFoundException::class); | ||
|
||
$data = new $collection(['foo', 'bar', 'baz']); | ||
|
||
$data->sole(function ($value) { | ||
return $value === 'invalid'; | ||
}); | ||
} | ||
|
||
/** | ||
* @dataProvider collectionClassProvider | ||
*/ | ||
public function testSoleThrowsExceptionIfMoreThanOneItemExistsWithCallback($collection) | ||
{ | ||
$this->expectException(MultipleItemsFoundException::class); | ||
|
||
$data = new $collection(['foo', 'bar', 'bar']); | ||
|
||
$data->sole(function ($value) { | ||
return $value === 'bar'; | ||
}); | ||
} | ||
|
||
/** | ||
* @dataProvider collectionClassProvider | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -977,6 +977,17 @@ public function testSomeIsLazy() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public function testSoleIsLazy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$data = $this->make([['a' => 1], ['a' => 2], ['a' => 3]]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$this->assertEnumeratesCollection($data, 3, function ($collection) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$collection->sole(function ($item) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return $item['a'] === 2; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Be sure to also import There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion again, I've just pushed up the new test changes :) |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public function testSortIsLazy() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$this->assertDoesNotEnumerate(function ($collection) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice if the query builder etc would throw the exact same exceptions when calling sole()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#37034 (comment)