count() emitting an E_WARNING

count(): parameter must be an array or an object that implements countable
warning: count(): parameter must be an array or an object that implements countable
php count
php 7.2 count fix
php array count values multidimensional array
count() php
php array length for loop
instanceof countable php

Prior to PHP 7.2 using count() on a scalar value or non-countable object would return 1 or 0.

For example: https://3v4l.org/tGRDE

var_dump(count(123)); //int(1)
var_dump(count(new stdclass)); //int(1)
var_dump(count('hello world'));  //int(1)
var_dump(count(null));  //int(0)

In the updates to PHP 7.2+, using count() as demonstrated above will emit a warning message.

An E_WARNING will now be emitted when attempting to count() non-countable types (this includes the sizeof() alias function).

Warning: count(): Parameter must be an array or an object that implements Countable [sic]

As a result many popular Frameworks will elevate the E_WARNING and throw an Exception instead.

[ErrorException] count(): Parameter must be an array or an object that implements Countable

The error elevation behavior was also commented on by the PHP developers.

Environments that display warnings or convert them to more severe errors/exceptions would be affected, but this should just bring attention to a bug in the code.

How can the previous behavior of count() be achieved in PHP 7.2+, that does not emit an E_WARNING, without modifying the error reporting setting and without using @count()?

As we discussed, there are multiple ways to achieve the original functionality of count() and not emit an E_WARNING.

In PHP 7.3 a new function was added is_countable, specifically to address the E_WARNING issue and the prevalence of applications adopting is_array($var) || $var instanceof \Countable in their code.

In PHP 7.2, a Warning was added while trying to count uncountable things. After that, everyone was forced to search and change their code, to avoid it. Usually, the following piece of code became standard:

if (is_array($foo) || $foo instanceof Countable) { // $foo is countable }

https://wiki.php.net/rfc/is-countable


Custom Function Replacement

For that reason it seems the best method of resolving the issue, is to perform the same functionality that PHP is doing with is_countable and creating a custom function to ensure compliance with the original functionality of count.

Example https://3v4l.org/8M0Wd

function countValid($array_or_countable, $mode = \COUNT_NORMAL)
{
    if (
        (\PHP_VERSION_ID >= 70300 && \is_countable($array_or_countable)) ||
        \is_array($array_or_countable) ||
        $array_or_countable instanceof \Countable
    ) {
        return \count($array_or_countable, $mode);
    }

    return null === $array_or_countable ? 0 : 1;
}

Result

array: 3
string: 1
number: 1
iterator: 3
countable: 3
zero: 1
string_zero: 1
object: 1
stdClass: 1
null: 0
empty: 1
boolt: 1
boolf: 1

Notice: Undefined variable: undefined in /in/8M0Wd on line 53
undefined: 0

Shim is_countable() function

Using the above replacement function, it is also possible to shim is_countable in PHP <= 7.2, so it is only used when needed, with minimal overhead.

Example https://3v4l.org/i5KWH

if (!\function_exists('is_countable')) {
    function is_countable($value)
    {
        return \is_array($value) || $value instanceof \Countable;
    }
}

function countValid($array_or_countable, $mode = \COUNT_NORMAL)
{
    if (\is_countable($array_or_countable)) {
        return \count($array_or_countable, $mode);
    }

    return null === $array_or_countable ? 0 : 1;
}

Ignore count() Warnings

As the functionality of count() has not changed and not did not typically emit warnings in the past. An alternative to using a custom function, is to ignore the warning outright by using the @ Error Control Operator

Warning: This approach has the impact of treating undefined variables as NULL and not displaying Notice: Undefined variable: message.

Example https://3v4l.org/nmWmE

@count($var);

Result

array: 3
string: 1
number: 1
iterator: 3
countable: 3
zero: 1
string_zero: 1
object: 1
stdClass: 1
null: 0
empty: 1
boolt: 1
boolf: 1
---
Undefined: 0

Replace count() using APD extension

As for replacing the internal PHP function count(). There is a PECL extension APD (Advanced PHP Debugger), that allows for override_function that works on core PHP functions. As the extension name suggests, it is technically meant for debugging, but is a viable alternative to replacing all instances of count for a custom function.

Example

\rename_function('count', 'old_count');
\override_function('count', '$array_or_countable,$mode', 'return countValid($array_or_countable,$mode);');

if (!\function_exists('is_countable')) {
    function is_countable($value)
    {
        return \is_array($value) || $value instanceof \Countable;
    }
}

function countValid($array_or_countable, $mode = \COUNT_NORMAL)
{
    if (\is_countable($array_or_countable)) {
        return \old_count($array_or_countable, $mode);
    }

    return null === $array_or_countable ? 0 : 1;
}

php - count() emitting an E_WARNING, How can the previous behavior of count() be achieved in PHP 7.2+, that does not emit an E_WARNING , without modifying the error reporting setting and without  Caution. count() can detect recursion to avoid an infinite loop, but will emit an E_WARNING every time it does (in case the array contains itself more than once) and return a count higher than may be expected.

The problem is that calling count() on a scalar or object that doesn't implement the Countable interface returns 1, which can easily hide bugs.

Given the following:

function handle_records(iterable $iterable)
{
    if (count($iterable) === 0) {
        return handle_empty();
    }

    foreach ($iterable as $value) {
        handle_value($value);
    }
}

Passing a Generator that yields nothing would not call handle_empty() nor handle_value(). Also, no indication would be given that neither were called.

By default, this will still return 1, though will additionally log a warning. If anything, this warning will bring attention to potential bugs in the code.

See Counting Non-Countables for further information.

count() emitting an E_WARNING, count() emitting an E_WARNING. count(): parameter must be an array or an object that implements countable warning: count(): parameter must be an array or an  Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Learn more PHP Warning: count(): Parameter must be an array or an object that implements Countable in

You can solve it by using "??"-operator. If the left side is null, the right side will be used. So as we have a empty array, our result will be zero.

count(null ?? [])

Another way would be to typecast it as an array.

count((array) null)

count() emitting an E_WARNING, An E_WARNING will now be emitted when attempting to count() non-countable types (this includes the sizeof() alias function). Warning: count(): Parameter must​  Dismiss Join GitHub today. GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.

count - Manual, Warn when counting non-countable types ¶. An E_WARNING will now be emitted when attempting to count() non-countable types (this includes the sizeof() alias  passed, a E_WARNING will be thrown for every such parameter. Be careful because your code may start emitting E_WARNING out of the blue. Possibly relevant: 0004415, 0004395. I have not tested the latest CVS version because I do not use CVS.

Backward incompatible changes - Manual, count() can detect recursion to avoid an infinite loop, but will emit an E_WARNING every time it does (in case the array contains itself more than once) and return  Counting reads in features with htseq-count ¶ Given a file with aligned sequencing reads and a list of genomic features, a common task is to count how many reads map to each feature. A feature is here an interval (i.e., a range of positions) on a chromosome or a union of such intervals.

Count all elements in an array, or something in an object, count() can detect recursion to avoid an infinite loop, but will emit an E_WARNING every time it does (in case the array contains itself more than once) and return  PHP's strlen function behaves differently than the C strlen function in terms of its handling of null bytes ('\0'). In PHP, a null byte in a string does NOT count as the end of the string, and any null bytes are included in the length of the string.

Comments
  • strlen()... count is for arrays or objects that implement Countable..
  • @LawrenceCherone count used to work for both. strlen does only work for strings and numbers. So all code bases have to be rewritten for this? why? add a check everywhere? write your own count function? sad
  • your passing a string/number, wrong function to use in first place..
  • Unfortunately you can't please everyone when you make progress, make a countLegacy() function yourself and do a simple find and replace through your codebase.
  • I'd roll back to 7.1. The PHP devs should have made 7.2 an 8.0; the commonly accepted guidelines for versioning numbers say to increment the major (first) number when changes break backwards compatibility. It's not unreasonable to expect a minor patch (increment to second number) to not have such breaks.
  • well, you are not wrong. The thing is, that is how this function worked. If you don't understand how the function works, it can lead to bugs, agreed. What they did now is they changed a core function because someone didn't like the old function. Breaking a lot of libraries.
  • I simply set a the variable to array before count like this. if(!is_array($arrayVariable)){ $arrayVariable = array(); }