is_countable
Checks whether a value can be passed to count() — an array or a Countable object.
is_countable(mixed $value): bool- Added in PHP 7.3.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$value | mixed | The value to check. |
Return value
booltrue if $value is an array or an object implementing Countable, false otherwise.
Changelog
- PHP 7.3.0is_countable() was added.
is_countable() tells you whether count() will work on a value. It is exactly equivalent to is_array($v) || $v instanceof Countable, packaged as one call.
It matters because count() stopped being forgiving. In PHP 7.2 counting a non-countable value became a warning, and since PHP 8.0 it throws a TypeError — count('abc') and count(null) are now fatal unless caught. Guarding with is_countable() turns that into a branch you control.
Countable is not the same as iterable
This is the part that surprises people. A Generator, an SplFileObject or any other Traversable that does not implement Countable can be looped over but has no size to report, so is_countable() returns false and count() throws. To size one of those you must consume it with iterator_count() or iterator_to_array() — and for a generator that also exhausts it, so you cannot then iterate it again.
When to reach for it
Use it in library code and in helpers that accept a mixed or union-typed value: a validator checking a minimum item count, a pagination helper, a template function deciding between "no results" and a list. It costs nothing and removes an entire class of PHP 8 fatal errors.
Example
When to use it
- Guarding count() in a helper whose parameter is mixed, so PHP 8 does not throw a TypeError
- Writing a template helper that shows 'no results' when a value is empty or not countable at all
- Validating a minimum or maximum number of items when the input may be an array or an ArrayObject
Frequently asked questions
What is the difference between is_countable() and is_array()?
is_array() is true only for real arrays, while is_countable() is also true for objects implementing Countable such as ArrayObject. Use is_countable() when your next call is count().
Why is is_countable() false for a Generator?
Because a generator produces values lazily and has no known size, so it does not implement Countable. Use iterator_count() to count one, keeping in mind that doing so consumes it.
Do I still need is_countable() in PHP 8?
More than ever — counting a non-countable value throws a TypeError in PHP 8, whereas PHP 7.2 to 7.4 only emitted a warning. Guard any count() whose argument is mixed or nullable.
More examples
A count() that cannot fatal
The guarded helper returns 0 for the string and for null, while the unguarded count() throws a TypeError telling you it needs Countable|array. In PHP 7.x that same call was only a warning, which is why old code breaks on upgrade.
<?php
function size(mixed $v): int {
return is_countable($v) ? count($v) : 0;
}
echo size(['a', 'b']), "\n";
echo size(new ArrayObject([1, 2, 3])), "\n";
echo size('abc'), "\n";
echo size(null), "\n";
try {
count('abc');
} catch (TypeError $e) {
echo $e->getMessage(), "\n";
}Generators are iterable but not countable
The generator is iterable but not countable, so counting it requires iterator_count() — which consumes it. The fourth line needs a fresh generator, because the first one is exhausted; reusing $g would return 0.
<?php
function rows(): Generator {
yield 1;
yield 2;
yield 3;
}
$g = rows();
var_dump(is_countable($g));
var_dump(is_iterable($g));
var_dump(iterator_count($g));
var_dump(iterator_count(rows()));Implementing Countable yourself
Adding the Countable interface and a count() method is all it takes to make an object work with both count() and is_countable(). A plain object without the interface stays false, no matter how many properties it has.
<?php
class Basket implements Countable {
public function __construct(private array $items) {}
public function count(): int { return count($this->items); }
}
$b = new Basket(['apple', 'pear']);
$plain = new stdClass();
var_dump(is_countable($b), count($b));
var_dump(is_countable($plain));
Discussion