在PHP 7.2之前,对标量值或不可数对象使用count()
将返回1
或0
。
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()
?
答案 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 }
因此,似乎解决该问题的最佳方法是执行与PHP对is_countable
相同的功能,并创建一个自定义函数以确保符合count
的原始功能
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
,因此仅在需要时使用它,而开销很小。
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:
消息的效果。
@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)