Arrays7 min readExamples run on PHP 8.5.10

count()

Learn how PHP 8.4 count() returns the number of elements in an array or Countable object, including recursive mode, error cases and common mistakes.

Signature

count(Countable|array $value, int $mode = COUNT_NORMAL): int

Purpose

count() tells you how many elements a container holds. Pass it an array and you get the number of entries in that array. Pass it an object that implements the Countable interface and PHP calls the object's own count() method and returns its result. It is one of the most common array functions, used for loop bounds, validation ("did the user select at least two options?") and reporting.

Signature

Parameters and defaults

  • $value: an array or a Countable object. No other type is accepted.
  • $mode: optional. The default COUNT_NORMAL (value 0) counts only the top-level entries. COUNT_RECURSIVE (value 1) also walks into nested arrays.

Return value and failure cases

The function returns an int: the number of elements. In PHP 8 and later, invalid input is not tolerated quietly:

  • A value that is neither an array nor a Countable object, such as null, false or a string, throws a TypeError.
  • A $mode other than COUNT_NORMAL or COUNT_RECURSIVE throws a ValueError.

Older PHP versions returned 1 for most non-countable values and 0 for null. Code written against that behaviour must be updated.

Example 1: basic counting

Only the number of entries matters, not the keys. A sparse array with keys 0, 5 and 10 has three elements, and an empty array has zero.

Example
<?php
$tags = ['php', 'arrays', 'count'];
$sparse = [0 => 'a', 5 => 'b', 10 => 'c'];
echo count($tags), "\n";
echo count($sparse), "\n";
echo count([]), "\n";
Output
3
3
0

Example 2: recursive counting

With COUNT_RECURSIVE, every nested element is counted, and the nested arrays themselves are counted too. Below, the two top-level entries (fruits and veggie) plus three items in each inner array give eight.

Example
<?php
$food = [
    'fruits' => ['orange', 'banana', 'apple'],
    'veggie' => ['carrot', 'collard', 'pea'],
];
echo json_encode([
    'normal' => count($food),
    'recursive' => count($food, COUNT_RECURSIVE),
]), "\n";
Output
{"normal":2,"recursive":8}

Example 3: Countable objects and safe counting

A class that implements Countable decides for itself what its count means. Here a basket reports the total quantity of its items rather than the number of lines. The helper safeCount() uses is_countable() so that unexpected values produce 0 instead of an exception. The last block shows an invalid mode.

Example
<?php
final class Basket implements Countable
{
    public function __construct(private array $items)
    {
    }

    public function count(): int
    {
        return array_sum(array_column($this->items, 'qty'));
    }
}

function safeCount(mixed $value): int
{
    return is_countable($value) ? count($value) : 0;
}

$basket = new Basket([
    ['sku' => 'A1', 'qty' => 2],
    ['sku' => 'B2', 'qty' => 3],
]);

echo json_encode([safeCount($basket), safeCount(null), safeCount('abc')]), "\n";

try {
    count([1, 2], 5);
} catch (ValueError $e) {
    echo "ValueError\n";
}
Output
[5,0,0]
ValueError

Edge cases

  • Gaps in keys do not matter. Only the number of stored entries counts, so count() is not the same as "highest index plus one".
  • null values still count. An array such as [null, null] has two elements. Use isset() on individual keys when you care about null values.
  • Recursive mode counts containers too. The result is not just the number of leaf values. Each nested array adds one for itself as well as one for each of its entries.
  • Self-referencing arrays. count() detects recursion to avoid an infinite loop, but it emits an E_WARNING each time and returns a higher number than you might expect.
  • Custom counts can be anything. For a Countable object, count() simply returns what the object's count() method returns, so the number may not equal any visible collection size.

Common mistakes

  1. Counting a value that may be null. Database or form code often yields null or false when nothing was found. In PHP 8 that throws a TypeError. Check with is_array() or is_countable() first, or make sure your functions always return arrays.
  2. Using count() on strings. It does not measure text length. Use strlen() for the number of bytes in a string.
  3. Expecting COUNT_RECURSIVE to count only leaves. If you need only the leaf values, write a small recursive function or flatten the array first.
  4. Recomputing in a loop condition. Writing for ($i = 0; $i < count($a); $i++) works, but if the array does not change inside the loop you can store the count in a variable first for clarity.
  5. Using count($x) > 0 when $x may be undefined. An undefined variable is null, which fails. Initialise arrays before use.
  6. Passing a magic number as the mode. Use the named constants so the intent is clear and only valid modes are used.
  • is_countable() checks whether a value can safely be passed to count().
  • is_array() checks that a value is an array.
  • isset() tests whether a variable or key exists and is not null.
  • empty() tests whether a value is considered empty, which is a quick way to check for no elements.
  • strlen() returns the length of a string.

Recap

count() returns the number of elements in an array or Countable object as an int. The default mode counts one level; COUNT_RECURSIVE includes nested arrays and their entries. In PHP 8, non-countable arguments throw a TypeError and invalid modes throw a ValueError, so guard uncertain values with is_countable().

Tested examples

Basic counting of lists, sparse arrays and empty arrays
<?php
$tags = ['php', 'arrays', 'count'];
$sparse = [0 => 'a', 5 => 'b', 10 => 'c'];
echo count($tags), "\n";
echo count($sparse), "\n";
echo count([]), "\n";
Output
3
3
0
Normal versus recursive counting
<?php
$food = [
    'fruits' => ['orange', 'banana', 'apple'],
    'veggie' => ['carrot', 'collard', 'pea'],
];
echo json_encode([
    'normal' => count($food),
    'recursive' => count($food, COUNT_RECURSIVE),
]), "\n";
Output
{"normal":2,"recursive":8}
Countable object, safe helper and invalid mode
<?php
final class Basket implements Countable
{
    public function __construct(private array $items)
    {
    }

    public function count(): int
    {
        return array_sum(array_column($this->items, 'qty'));
    }
}

function safeCount(mixed $value): int
{
    return is_countable($value) ? count($value) : 0;
}

$basket = new Basket([
    ['sku' => 'A1', 'qty' => 2],
    ['sku' => 'B2', 'qty' => 3],
]);

echo json_encode([safeCount($basket), safeCount(null), safeCount('abc')]), "\n";

try {
    count([1, 2], 5);
} catch (ValueError $e) {
    echo "ValueError\n";
}
Output
[5,0,0]
ValueError