PHP简写加法运算符-未定义的偏移量。

4
我正在使用PHP的简写加法运算符来计算多维数组中特定id出现的次数:
$source['tally'] = array();

foreach ($items as $item) {
    $source['tally'][$item->getId()] += 1;
}

第一次它遇到一个新的id时,它将其“tally”值设置为1,然后每次找到它时都会递增。
代码可以正常工作(我得到了正确的总数),但是每当它发现一个新的id时,PHP就会给出一个“未定义的偏移量”通知。
我知道我可以在php.ini中关闭通知,但我想知道PHP不赞成我的技术的原因。
像这样动态创建新的键/偏移量是否被认为是不好的做法,是否应该采取更好的方法?
请注意:为了帮助澄清初始反馈,我确实理解为什么会出现通知。我的问题是我是否应该对其进行任何处理还是只接受通知。如果我的问题没有表达清楚,请谅解。

1
$source ['tally'] = array(); 是一个原始数组。没有初始化。这可能是原因。我猜是这样。 - Kris
感谢 - 无论是否初始化代码,都会发出通知。如果省略该行,则除了已经提到的“未定义偏移量”通知外,还会添加“未定义索引”通知。 - cantera
偏移量也是类似的,因为它不包含任何值,所以像您的偏移量还未定义一样,'+=' 尝试添加到一个已存在的值;因此第一次会分配一个警告。 - Kris
有人知道如何在 PHP 8 的限制条件下使用这个简写操作符 += 吗?当尝试添加到未设置的值时会出现警告,这会导致代码膨胀,特别是对于动态生成的值。有没有什么解决方法? - Martin
4个回答

3

如果您只想隐藏通知,可以使用错误控制运算符

$source['tally'] = array();

foreach ($items as $item) {
    @$source['tally'][$item->getId()]++;
}

然而,在大多数情况下,您应该初始化变量,例如在循环内添加以下代码:
if (!isset( $source['tally'][$item->getId()] ))
{
   $source['tally'][$item->getId()] = 0;
}

他的代码并不是没有问题,也不是为了消除警告。初始化值被认为是良好的实践。如果他尝试在C++而不是PHP中编写这段代码,那么代码将会闹出大问题。 - Madara's Ghost
1
至少 OP 已经开启了通知,并且确实在关注它们。 - Gustav Bertram
在 PHP 8 中,这将成为一个警告,并强制输出大量的代码膨胀 :-( - Martin

3

你必须明白PHP提示信息是一个工具。它们存在的目的是为了让你在编写代码时获得额外的帮助,便于轻松检测潜在错误。未初始化的变量就是典型的例子。很多开发者会问:如果不强制初始化变量,为什么PHP还会抱怨呢?因为它正试图提供帮助:

$item_count = 0;
while( do_some_stuff() ){
     $iten_count++; // Notice: Undefined variable: iten_count
}
echo $item_count . ' items found';

哎呀,我打错了变量名。

$res = mysql_query('SELECT * FROM foo WHERE foo_id=' . (int)$_GET['foo_id']);
// Notice: Undefined index: foo_id

哎呀,我没有提供默认值。

你的情况只是另一个例子。如果你正在递增错误的数组元素,你想知道。


当代码变量(如数组内容)可以完全动态生成时,强制代码块定义默认值的概念本身并不是不好的,但糟糕的是在PHP 8+中将其标记为警告级别错误。 - Martin

2
使用+=(或其他增强赋值运算符)假设该键已经存在某个值。由于第一次遇到ID时并非如此,因此会发出一个通知,并假定为0

感谢您的回复。我明白为什么会发出通知,但是PHP为什么在乎关键字是否已经存在呢?毕竟它只是要按照我的指示将值设置为1。即使这样可行,为什么不认为这是一个好的做法呢? - cantera
它不会设置它,直到检索到已存在该键的值。但是首先根本没有该键的元素。 - Ignacio Vazquez-Abrams
1
因为如果您尝试读取不存在的值,很可能会出现错误。 - ThiefMaster
PHP允许这种行为,它不会给你一个错误,只会给你一个提示,因为虽然你的脚本仍然可以工作,但这是一种不好的编程实践,在其他语言中这样做将无法工作。 - Alasdair

1

这是因为您没有将数组初始化为包含0的初始值。请注意,代码可能会正常工作,但是最好的做法是初始化您即将执行操作的所有变量。因此,以下代码是您应该具有的示例:

<?php
    $source['tally'] = array();

    foreach ($items as $item) {
        //For each $item in $items,
        //check if that item doesn't exist and create it (0 times).
        //Then, regardless of the previous statement, increase it by one.
        if (!isset($source['tally'][$item->getID()]) $source['tally'][$item->getID()] = 0;
        $source['tally'][$item->getId()] += 1;
    }
?>

PHP关心这个的实际原因主要是为了警告您空值(就像如果您尝试读取它一样)。这是一种错误,不是致命的、终止脚本运行的错误,而是一种比较微妙安静的错误。但是您仍然应该修复它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接