count()发出E_WARNING

时间:2018-04-04 23:42:45

标签: php php-7.2

在PHP 7.2之前,对标量值或不可数对象使用count()将返回10

例如: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)

updates to PHP 7.2+中,如上所示使用count()会发出警告消息。

  

当尝试count()不可数类型(包括sizeof()别名函数)时,现在将发出 E_WARNING

     

警告:count():参数必须是实现Countable的数组或对象    [sic]

因此,许多流行的框架将提升E_WARNING并抛出异常。

  

[ErrorException] count():参数必须是数组或实现Countable

的对象

PHP开发人员也评论了错误提升行为。

  

显示警告或将其转换为更严重的错误/异常的环境会受到影响,但这只会引起注意代码中的错误。

如何在不修改错误报告设置且不使用count()的情况下,在PHP 7.2+中实现E_WARNING的先前行为,但不会发出@count()

3 个答案:

答案 0 :(得分:6)

问题是在没有实现Countable接口的标量或对象上调用count()会返回1,这可以很容易地隐藏错误。

鉴于以下内容:

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

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

传递不产生任何内容的生成器不会调用handle_empty()handle_value() 此外,没有任何迹象表明两者都没有被召唤。

默认情况下,这仍将返回1,但会另外记录警告。如果有的话,这个警告会引起注意代码中潜在的错误。

有关详细信息,请参阅Counting Non-Countables

答案 1 :(得分:6)

正如我们所讨论的,有多种方法可以实现count()的原始功能并且不发出E_WARNING

在PHP 7.3中,添加了一个is_countable新功能,专门用于解决E_WARNING问题以及应用程序在其代码中采用is_array($var) || $var instanceof \Countable的情况。

  

在PHP 7.2中,尝试计数不可数时添加了警告   东西。此后,每个人都被迫搜索和更改他们的   代码,以避免它。通常,下面的代码片段变成   标准:

     

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

     

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

因此,似乎解决该问题的最佳方法是执行与PHP对is_countable相同的功能,并创建一个自定义函数以确保符合count的原始功能

示例: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;
}

结果:

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

此外,您还可以在is_countable中填充PHP <= 7.2,因此仅在需要时使用它,而开销很小。

示例: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;
}

由于count()的功能未更改,并且过去通常不会发出警告。使用自定义函数的另一种方法是使用@ Error Control Operator

完全忽略警告

警告::这种方法具有将未定义的变量视为NULL且不显示Notice: Undefined variable:消息的效果。

示例:https://3v4l.org/nmWmE

@count($var);

结果:

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

关于替换内部PHP函数count()。有一个PECL扩展APD(高级PHP调试器),它允许override_function在核心PHP函数上工作。正如扩展名所暗示的那样,从技术上讲,它是用于调试的,但对于将count的所有实例替换为自定义函数,这是一种可行的选择。

\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;
}

答案 2 :(得分:1)

您可以使用“ ??”运算符来解决它。如果左侧为空,则将使用右侧。因此,由于我们有一个空数组,结果将为零。

count(null ?? [])

另一种方法是将其类型转换为数组。

count((array) null)