【问题标题】:PHP loop through array of object gives unexpected resultPHP循环遍历对象数组给出了意想不到的结果
【发布时间】:2013-09-01 12:32:51
【问题描述】:

我有以下 PHP 代码来为每个帖子设置 parentId。 每个数据的parentId都成为最后一个post 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
                        )

                )

        )

)

【问题讨论】:

标签: php loops object reference


【解决方案1】:

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

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

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

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 默认返回对象,而不是关联数组。不久前我运行了一些测试脚本,结果证明:编码-解码方法实际上比强制转换每个关联数组要快...

【讨论】:

    【解决方案2】:

    好的,我误解了你的问题,由于你重用了你最终会遇到引用问题的数据对象,这可以通过使用克隆来避免,如下所示

    <?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); 
    

    【讨论】:

    • 你错了他通过引用传递,因此他正在处理数组内的数据
    • 而不是克隆,直到数据属性被赋值后才使用对象,这样方式性能更高,也更容易
    • 是的——我只是不想改变这个例子的传入数据,如果你当然可以避免所有这些对象和数组之间的混合——更好
    猜你喜欢
    • 2019-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 2017-03-09
    • 2019-05-19
    相关资源
    最近更新 更多