PHP loop through an object array gives an unexpected result

I have the following php code to set parentId for each post. By default, the parentId of all data becomes the last message identifier. What is wrong with my logic?

btw, if I change it to an array, everything becomes fine. 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 ) ) ) ) 
+4
source share
2 answers

All things considered, the real problem is the following, after a second look at your code, how you set the data property. Starting with PHP5, objects are passed / assigned by default link. Remember the days of PHP4? ( $newInstance = &new SomeClass(); ), PHP5 now uses references for objects, 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, all three instances will reflect the same change!

I recently posted a long answer on links in loops here , it might be worth a look, because loop on a link is not the best way to go about your business.

Some code check:
Instead of creating all these arrays and separately relating them to objects, I would simply 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, json_encode may seem ineffective, only until json_decode it, but json_decode returns objects, not associative arrays by default. I have already run several test scripts several times, as it turned out: the decoding-decoding approach was actually faster than listing each associative array ...

+5
source

Well, I misunderstood your problem due to the fact that you are reusing the data object, resulting in a reference problem, this can be avoided by using a clone, as shown 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
source

Source: https://habr.com/ru/post/1499549/


All Articles