【问题标题】:PHP something wrong with refrence variable in foreachPHP foreach 中的引用变量有问题
【发布时间】:2021-05-27 15:59:39
【问题描述】:

我有这样的数据:

$a = [
"attr1"=> null,
"list"=> [
    [
        "other_attr"=> 47,
        "personal"=> [
            [
                "id"=> 3071,
                "quantity"=> 4,
                "price"=> 340000
            ]
        ]
    ],
    [
        "other_attr"=> 47,
        "group"=> [
            [
                "id"=> 3086,
                "quantity"=> 2,
                "price"=> 350000
            ]
        ]
    ]
]];

并具有以下功能:

foreach( $a['list'] as &$value ){
if (!empty($value["personal"])) {
    foreach ($value["personal"] as &$item) {
        $item['F'] = "TREDA";
    }
    foreach ($value["personal"] as $item) {
        print("do some thing here with new attribute F\n");
    }
    $value["C"] = 32213;
}
 if (!empty($value["group"])) {
     foreach  ($value['group'] as $item) {
         print("Do some thing here\n");
     }
    $value["C"] = "AAAA";
}
}

$a 的预期结果如下:

{"attr1":null,"list":[{"other_attr":47,"personal":[{"id":3071,"quantity":4,"price":340000,"F":"TREDA"}],"C":32213},{"other_attr":47,"group":[{"id":3086,"quantity":2,"price":350000}],"C":"AAAA"}]}

但实际数据错误如下:

{"attr1":null,"list":[{"other_attr":47,"personal":[{"id":3086,"quantity":2,"price":350000}],"C":32213},{"other_attr":47,"group":[{"id":3086,"quantity":2,"price":350000}],"C":"AAAA"}]}

Id 3071 已替换为 Id 3086

谁能给我解释一下这里有什么问题?

感谢您的帮助!

链接PHPOnline Sandbox中的P/S代码演示

【问题讨论】:

  • 您需要在$value['personal']的第一个foreach循环中更新/修改$item后添加unset($item);
  • 在提供的沙盒链接上更新
  • 引用PHP.net: Warning Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset(). Otherwise you will experience the following behavior
  • 不幸的是,PHP 不维护循环内变量的局部范围(例如,与 Java 不同)。请参阅示例:sandbox.onlinephpfunctions.com/code/… 因此,进一步引用同一变量可能会导致代码中出现未定义的行为。

标签: php foreach php-7.2


【解决方案1】:

正如您所发现的,通过引用传递可能是一种危险的游戏。这可能并不明显,但您在此循环中创建了对 $item 的引用:

foreach ($value["personal"] as &$item) {

这仍然是对$value["personal"] 中第一个条目的引用,即使您不再处于该循环中。所以这意味着稍后在你的代码中:

foreach ($value['group'] as $item) {

您正在引用相同的 $item 变量(这是对 $value["personal"] 中的条目的引用。

因此,personal 内部的条目被替换为 group 内部的条目。

如果您真的不需要引用,最好(并且更安全)使用数组索引来更改值,例如

foreach ($value["personal"] as $index => $item) {
    $item['F'] = "TREDA";
    $value['personal'][$index] = $item;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 2016-07-03
    • 1970-01-01
    • 2011-05-08
    相关资源
    最近更新 更多