4

I have the following PHP code to set parentId for each post. The parentId of each data all become the last post ID. What's wrong with my logic?

btw, if I change it to array, everythings becomes ok. Please help!

$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;

Results:

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
                        )

                )

        )

)
1

2 Answers 2

5

All things considered, the real issue here is, after a second glance at your code, the way you're setting the data property. Since PHP5, objects are passed/assigned by reference by default. Remember the PHP4 days? ($newInstance = &new SomeClass();), PHP5 uses references for objects now, so when you do:

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

Then, all three objects are assigned the same object (By reference!), so if you change it for the first time around, all three instances will reflect the same change!

I've recently posted a lengthy answer on references in loops here, it might be worth a look, because looping by reference isn't the best way to go about your business.

Some code-review:
Instead of constructing all these arrays, and cast them to objects individually, I'd just do this:

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

At first, it might seem inefficient to json_encode something, just to json_decode it, but json_decode returns objects, instead of associative arrays by default. I've ran a few tests scripts not too long ago, as it turned out: the encode-decode approach was actually faster than casting each associative array...

Sign up to request clarification or add additional context in comments.

Comments

3

Okay, i misunderstood your problem, due to the fact that you reuse the data object you end up with a reference problem, this can be avoided by using clone, as seen below

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

3 Comments

you're wrong he makes a pass by reference, therefore he's working on the data inside the array
rather then cloning, not using objects until after the data property has been assigned its values is way more performant and a lot easier, too
yes - i just didn't wanted to change the ingoing data for this example, if you of course can avoid all this mix between objects and and arrays in the first place – even better

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.