PHP通过AJAX发送带有多维数组的奇怪之处

时间:2018-06-18 15:35:51

标签: javascript php arrays ajax foreach

我猜这是一个已知的问题我只是在某种程度上从未遇到过。我有一个通过AJAX发送到PHP的多维数组,如下所示:

let pd = {
    vids: $.map(yt_vids_preview.find('tr:has(td :checked)'), function(el) {
        let vid = $(el).data('vid');
        return {
            vid_id: vid.contentDetails.videoId
    }; })
};
$.ajax({data: pd, url: 'foo.php', type: 'post'})

根据print_r($_POST['vids'])

,这是PHP收到的内容
Array
(
    [0] => Array
        (
            [vid_id] => kCkrVN7IVbo
        )

    [1] => Array
        (
            [vid_id] => dNVxfnb8fjo
        )

    [2] => Array
        (
            [vid_id] => rJEEYTzYiAE
        )
)

一切都好。三个不同的视频。

现在是奇怪的。

foreach($_POST['vids'] as $arr) echo $arr['vid_id']."\n";

由于某种原因,这输出:

kCkrVN7IVbo
dNVxfnb8fjo
dNVxfnb8fjo

其中一件物品已被复制,价格昂贵,另外一件已完全省略。我已经省略了所有其他代码,并且没有覆盖$arr或类似的东西。

如果我使用基本的for()循环,甚至是array_walk()之类的迭代回调函数,都不会发生这种情况:

array_walk($_POST['vids'], function($arr) { echo $arr['vid_id']."\n"; });

给出:

kCkrVN7IVbo
dNVxfnb8fjo
rJEEYTzYiAE

到底是怎么回事?

2 个答案:

答案 0 :(得分:1)

不确定这是否可能对其他人有所帮助,但事实证明,$arr循环中foreach()的先前使用是在同一函数中更早出现的,应该归咎于此。

至关重要的是,这个是通过参考指定的,即

foreach($_POST['vids'] as $i => &$arr) {
    //...
}

出于某些原因,我没有完全低估,当我后来在另一个$arr作业中使用foreach()时,这会导致问题。我知道它是从早期的参考作业泄漏,但为什么要复制一个并省略另一个视频ID?奇怪的结果......

foreach($_POST['vids'] as $arr) echo $arr['vid_id']."\n";

答案 1 :(得分:1)

考虑你在问题中显示的foreach循环,以及答案中的那个:

// First
foreach($_POST['vids'] as $i => &$arr) {
    //...
}

// Second
foreach($_POST['vids'] as $arr) echo $arr['vid_id']."\n";

第一个循环在$arr$_POST['vids']的每个元素之间创建一个引用,但是对最后一个元素的引用永远不会被设置,因此$arr实际上仍然引用最后一个元素数组

这可能听起来有点不直观,但这意味着,$_POST['vids']的最后一个元素会在您更改$arr的值时发生更改,因此在$_post['vids']的最后一次迭代中,你实际上正在做$arr = $arr,这个值就是你在循环的前一次迭代中所做的那样。

从图形上看,这样的事情正在发生。 (这不是有效的PHP)

$arr = [1, 2, 3, 4, 5 <=> $value] 
// This represents the last item on arr being a reference of $value (<=> is not being used as an actual operator, its representing the reference)

foreach($arr as $value) {
    echo $arr;
}
// OUTPUT:
[1, 2, 3, 4, 1 <=> $value] // $value equals the first element of the array
[1, 2, 3, 4, 2 <=> $value] // $value equals the 2nd element of the array
[1, 2, 3, 4, 3 <=> $value] // $value equals the 3rd element
[1, 2, 3, 4, 4 <=> $value] // $value equals the 4th element
[1, 2, 3, 4, 4 <=> $value] // $value equals itself (4th element)

要解决此问题,您只需要使用unset($arr)

在第二个循环之前中断引用
unset($arr);
foreach($_POST['vids'] as $arr) echo $arr['vid_id']."\n";