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

Utk*_*nos 5 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'})
Run Code Online (Sandbox Code Playgroud)

这是PHP收到的内容,根据print_r($_POST['vids']):

Array
(
    [0] => Array
        (
            [vid_id] => kCkrVN7IVbo
        )

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

    [2] => Array
        (
            [vid_id] => rJEEYTzYiAE
        )
)
Run Code Online (Sandbox Code Playgroud)

都好.三个不同的视频.

现在为了古怪.

foreach($_POST['vids'] as $arr) echo $arr['vid_id']."\n";
Run Code Online (Sandbox Code Playgroud)

由于某种原因,这输出:

kCkrVN7IVbo
dNVxfnb8fjo
dNVxfnb8fjo
Run Code Online (Sandbox Code Playgroud)

其中一个项目已被复制,而另一个项目则是昂贵的,已完全省略.我省略了所有其他代码,没有覆盖$arr或类似的东西.

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

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

得到:

kCkrVN7IVbo
dNVxfnb8fjo
rJEEYTzYiAE
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事?

Ara*_*Rey 1

考虑到您在问题中显示的 foreach 循环以及答案中的 foreach 循环:

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

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

第一个循环在$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)
Run Code Online (Sandbox Code Playgroud)

要解决此问题,您只需使用以下命令在第二个循环之前中断引用unset($arr)

unset($arr);
foreach($_POST['vids'] as $arr) echo $arr['vid_id']."\n";
Run Code Online (Sandbox Code Playgroud)