Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/Illuminate/Collections/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,21 @@ public function containsOneItem(?callable $callback = null): bool
return $this->count() === 1;
}

/**
* Determine if the collection contains multiple items. If a callback is provided, determine if multiple items match the condition.
*
* @param (callable(TValue, TKey): bool)|null $callback
* @return bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it would make sense to add an assertion here and in the two corresponding methods

Suggested change
* @return bool
* @return bool
* @phpstan-assert-if-true non-empty-array<TKey, TValue> $this->items

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed suit with the containsOneItem method doc block:

/**
* Determine if the collection contains exactly one item. If a callback is provided, determine if exactly one item matches the condition.
*
* @param (callable(TValue, TKey): bool)|null $callback
* @return bool
*/
public function containsOneItem(?callable $callback = null): bool
{
if ($callback) {
return $this->filter($callback)->count() === 1;
}
return $this->count() === 1;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nobody said, there wasn't room for improvement. With this argument, we'd be stuck in the stone age forever.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol easy -- its a doc block

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's more than a comment. It improves static analysis.

*/
public function containsManyItems(?callable $callback = null): bool
{
if ($callback) {
return $this->filter($callback)->count() > 1;
}

return $this->count() > 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the goal here is to just see if there are at least two items in the collection matching the filter, wouldn't it be better to call each() and then break the loop once you've met the limit of 2?

Copy link
Contributor Author

@stevebauman stevebauman Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is basically identical to the existing containsOneItem method to maintain consistency between the two:

public function containsOneItem(?callable $callback = null): bool
{
if ($callback) {
return $this->filter($callback)->count() === 1;
}
return $this->count() === 1;
}

}

/**
* Join all items from the collection using a string. The final items can use a separate glue string.
*
Expand Down
7 changes: 7 additions & 0 deletions src/Illuminate/Collections/Enumerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,13 @@ public function isNotEmpty();
*/
public function containsOneItem();

/**
* Determine if the collection contains multiple items.
*
* @return bool
*/
public function containsManyItems();

/**
* Join all items from the collection using a string. The final items can use a separate glue string.
*
Expand Down
10 changes: 10 additions & 0 deletions src/Illuminate/Collections/LazyCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,16 @@ public function containsOneItem()
return $this->take(2)->count() === 1;
}

/**
* Determine if the collection contains multiple items.
*
* @return bool
*/
public function containsManyItems(): bool
{
return $this->take(2)->count() > 1;
}

/**
* Join all items from the collection using a string. The final items can use a separate glue string.
*
Expand Down
14 changes: 14 additions & 0 deletions tests/Support/SupportCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,20 @@ public function testContainsOneItem($collection)
$this->assertFalse(collect(['ant', 'bear', 'cat'])->containsOneItem(fn ($word) => strlen($word) > 4));
}

#[DataProvider('collectionClassProvider')]
public function testContainsManyItems($collection)
{
$this->assertFalse((new $collection([]))->containsManyItems());
$this->assertFalse((new $collection([1]))->containsManyItems());
$this->assertTrue((new $collection([1, 2]))->containsManyItems());
$this->assertTrue((new $collection([1, 2, 3]))->containsManyItems());

$this->assertTrue(collect([1, 2, 2])->containsManyItems(fn ($number) => $number === 2));
$this->assertFalse(collect(['ant', 'bear', 'cat'])->containsManyItems(fn ($word) => strlen($word) === 4));
$this->assertFalse(collect(['ant', 'bear', 'cat'])->containsManyItems(fn ($word) => strlen($word) > 4));
$this->assertTrue(collect(['ant', 'bear', 'cat'])->containsManyItems(fn ($word) => strlen($word) === 3));
}

public function testIterable()
{
$c = new Collection(['foo']);
Expand Down
15 changes: 15 additions & 0 deletions tests/Support/SupportLazyCollectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,21 @@ public function testContainsOneItem()
$this->assertFalse($multipleCollection->containsOneItem());
}

public function testContainsManyItems()
{
$emptyCollection = new LazyCollection([]);
$this->assertFalse($emptyCollection->containsManyItems());

$singleCollection = new LazyCollection([1]);
$this->assertFalse($singleCollection->containsManyItems());

$multipleCollection = new LazyCollection([1, 2]);
$this->assertTrue($multipleCollection->containsManyItems());

$manyCollection = new LazyCollection([1, 2, 3]);
$this->assertTrue($manyCollection->containsManyItems());
}

public function testDoesntContain()
{
$collection = new LazyCollection([1, 2, 3, 4, 5]);
Expand Down