Collection::isEmpty
Returns true when the collection contains no items at all.
Collection::isEmpty(): boolReturn value
boolTrue when the collection holds no items, false when it holds at least one — regardless of whether those items are themselves falsy.
isEmpty reports whether the collection holds any items. Its inverse, isNotEmpty, saves you a negation and reads better in a conditional. Both are cheap — they check the underlying array, they do not iterate.
When to reach for it
Use it wherever you would otherwise write count($x) === 0: guarding a template section, returning early from a service, choosing between a result list and an empty state. In Blade it is the idiomatic partner to @forelse, and in service code it is the honest way to ask "did anything survive the filter?".
It is also the reliable way to distinguish an empty collection from one whose first item is null — a distinction first() alone cannot express, since it returns null for both.
The thing that trips people up
Emptiness is about the item count, not about the items' truthiness. collect([0, null, false, '']) is not empty: it holds four items, every one of them falsy. If you meant "contains nothing meaningful", filter first and then ask — $c->filter()->isEmpty().
Note too that a Collection object is always truthy in a plain boolean context, so if ($collection) is true even when the collection is empty. Always call the method rather than relying on the object itself.
Example
When to use it
- Return an early response from a service when a filtered result set came back with nothing.
- Guard a template section that renders a list, showing an empty state instead.
- Distinguish 'no rows' from 'a row whose value is null' after calling first().
Frequently asked questions
Is a collection of falsy values considered empty?
No. isEmpty() counts items, not truthiness, so collect([0, null, false, '']) returns false. Chain filter() first if you want to treat falsy entries as nothing: $c->filter()->isEmpty().
Can I just write if ($collection) instead?
No — a Collection object is always truthy, even when it holds no items, so that check always passes. Call isEmpty() or isNotEmpty() explicitly.
What is the difference between isEmpty() and count() === 0?
They report the same thing for a Collection, but isEmpty() states the intent directly and pairs with isNotEmpty(). On a LazyCollection, counting has to enumerate the whole source while isEmpty() only needs the first item.
More examples
Empty of items versus empty of meaning
The output is bool(false), 4, bool(true), bool(true). The last line is the important one: casting the object to bool gives true even for an empty collection, which is why if ($collection) silently does the wrong thing. isEmpty() and isNotEmpty() are the only reliable checks.
<?php
$values = collect([0, null, false, '']);
var_dump($values->isEmpty()); // four items exist
echo $values->count(), PHP_EOL;
// Ask the question you actually meant:
var_dump($values->filter()->isEmpty());
// A Collection object is ALWAYS truthy, even when empty.
$empty = collect([]);
var_dump((bool) $empty);Early return in service code
The first branch prints "nothing to chase" because the filter removed both rows. The final line prints "fallback": whenEmpty invokes the callback only on an empty collection and returns whatever it produces, which keeps a fluent chain intact where an if statement would break it.
<?php
$overdue = collect([
['id' => 1, 'days_late' => 0],
['id' => 2, 'days_late' => 0],
])->filter(fn (array $i) => $i['days_late'] > 0);
if ($overdue->isEmpty()) {
echo 'nothing to chase', PHP_EOL;
} else {
echo 'chasing ', $overdue->count(), ' invoices', PHP_EOL;
}
// whenEmpty runs a callback instead of branching.
echo collect([])->whenEmpty(fn ($c) => $c->push('fallback'))->implode(','), PHP_EOL;Empty versus a null first item
Both calls to first() print NULL, so testing the result against null cannot tell the two collections apart. isEmpty() reports true and false respectively. The commented Blade fragment is the template-side equivalent — @forelse falls through to @empty on exactly the condition isEmpty() reports.
<?php
$a = collect([]);
$b = collect([null, 'x']);
var_dump($a->first(), $b->first()); // indistinguishable
var_dump($a->isEmpty(), $b->isEmpty()); // now they differ
// In Blade, @forelse expresses the same branch:
// @forelse ($orders as $order) ... @empty <p>No orders yet.</p> @endforelse
Discussion