PHP循环遍历对象数组会产生意外结果

时间:2013-08-29 07:30:26

标签: php loops object reference

我有以下PHP代码为每个帖子设置parentId。 每个数据的parentId都成为最后一个帖子ID。 我的逻辑出了什么问题?

不过,如果我把它改成阵列,那么每一件事都可以。请帮忙!

$data = array(
    (object)array('name' => 'myname')
);
$posts = array(
    (object)array('ID' => 1, 'data'=>$data),
    (object)array('ID' => 2, 'data'=>$data),
    (object)array('ID' => 3, 'data'=>$data)
);
foreach($posts as &$post){
    $post->data[0]->parentId = $post->ID;
}
print '<pre>';print_r($posts);die;
die;

结果:

Array
(
    [0] => stdClass Object
        (
            [ID] => 1
            [data] => Array
                (
                    [0] => stdClass Object
                        (
                            [name] => myname
                            [parentId] => 3 // expect to be 1
                        )

                )

        )

    [1] => stdClass Object
        (
            [ID] => 2
            [data] => Array
                (
                    [0] => stdClass Object
                        (
                            [name] => myname
                            [parentId] => 3 // expect to be 2 !!!
                        )

                )

        )

    [2] => stdClass Object
        (
            [ID] => 3
            [data] => Array
                (
                    [0] => stdClass Object
                        (
                            [name] => myname
                            [parentId] => 3
                        )

                )

        )

)

2 个答案:

答案 0 :(得分:5)

考虑到所有事情,这里的真正的问题是,在您第二眼看到您的代码后,您将设置data属性的方式。从PHP5开始,默认情况下,对象通过引用传递/分配 。还记得PHP4天吗? ($newInstance = &new SomeClass();),PHP5现在使用对象的引用,所以当你这样做时:

$data = array(
    (object)array('name' => 'myname')//create object
);

然后,所有三个对象都被分配了相同的对象(通过 reference!),所以如果你第一次更改它,那么所有三个实例都将反映相同的变化!

I've recently posted a lengthy answer on references in loops here,可能值得一看,因为通过引用循环并不是开展业务的最佳方式。

一些代码审核:
我没有构建所有这些数组,而是将它们单独转换为对象,我只是这样做:

$data = array(
    array('name' => 'myname')
);
$posts = array(
    array('ID' => 1, 'data'=>$data),
    array('ID' => 2, 'data'=>$data),
    array('ID' => 3, 'data'=>$data)
);
foreach($posts as $k => $post)
{
    $posts[$k]['data'][0]['parentId'] = $posts[$k]['ID'];
}
$posts = json_decode(json_encode($posts));//turns everything into objects
print_r($posts);

首先,json_encode某些内容似乎效率低下,只有json_decode,但json_decode默认返回对象而不是关联数组。不久前我运行了一些测试脚本,结果证明:编码 - 解码方法实际上比投射每个关联数组更快......

答案 1 :(得分:3)

好的,我误解了你的问题,因为你重复使用数据对象最终会引用一个引用问题,这可以通过使用clone来避免,如下所示

<?php

$data = (object) array('name' => 'myname');

$posts = array(
    (object) array('ID' => 1, 'data'=> array(clone $data)),
    (object) array('ID' => 2, 'data'=> array(clone $data)),
    (object) array('ID' => 3, 'data'=> array(clone $data))
);

foreach($posts as $postKey => $post){
    $posts[$postKey]->data[0]->parentId = $posts[$postKey]->ID;
}
print '<pre>';
print_r($posts);