6

I have following code:

foreach($foo as $n=>$ia) {
    foreach($ia as $i=>$v) {
    $bar[$i]->$n = $v; //here I have 'Creating default object...' warning
    }
}

If I add:

$bar[$i] = new stdClass;
$bar[$i]->$n = $v;

to fix it. Then values in objects in array 'bar' not sets. For example, I have array:

 $foo = array(
 "somefield" => array("value1", "value2", "value3"),
 "anotherfield" => array("value1", "value2", "value3")
 );

On output I should get:

$bar[0]->somefield = value1
$bar[1]->anotherfield = value2

But in practice I get:

$bar[0]->somefield = null //(not set)
$bar[1]->anotherfield = null //too

How should I update the code to get it work?

hakre
  • 193,403
  • 52
  • 435
  • 836
PASAf
  • 115
  • 1
  • 7
  • 3
    For the life of me I cannot understand what this code is supposed to do and what the logic behind the desired output is. If it's so dense it definitely could use a rewrite. – Jon Feb 05 '13 at 14:35
  • 1
    Please use brackets to wrap the foreach statements! – Martin Samson Feb 05 '13 at 15:24
  • 1
    As @MartinSamson says, the lack of brackets in the code given is disturbing, but the way you've written the question, with the 'if I add...' bit makes it hard to see what your code actually looks like - Please update the question to show the actual code that you have. – SDC Feb 05 '13 at 16:22

2 Answers2

7

Problem:

The problem with your code is, that if you use the first attempt,

$bar[$i]->$n = $v;

a default empty object will be created for if you use the -> operator on a non existent array index. (NULL). You'll get a warning as this is a bad coding practice.

The second attempt

$bar[$i] = new stdClass;
$bar[$i]->$n = $v;

will simply fail as you overwrite $bar[$i] each loop.

Btw the code above won't work even with PHP5.3


Solution:

I would prefer the following code example because:

  • it works without warnings :)
  • it don't uses the inline initialization features like in your question. I think its is good coding practice to declare $bar explicitely as empty array() and to create the objects using: new StdClass().
  • it uses descriptive variable names help to understand what the code is doing.

code:

<?php

$foo = array(
  "somefield" => array("value1", "value2", "value3"),
  "anotherfield" => array("value1", "value2", "value3")
);

// create the $bar explicitely
$bar = array();

// use '{ }' to enclose foreach loops. Use descriptive var names
foreach($foo as $key => $values) {
    foreach($values as $index => $value) {
        // if the object has not already created in previous loop
        // then create it. Note, that you overwrote the object with a 
        // new one each loop. Therefore it only contained 'anotherfield'
        if(!isset($bar[$index])) {
            $bar[$index] = new StdClass();
        }
        $bar[$index]->$key = $value;
    }
}

var_dump($bar);
hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • Thank you very much, it worked like a charm. Sorry for my ugly written example, yours really much better. – PASAf Feb 05 '13 at 16:26
  • 1
    no problem! If you want to hear my opinion.. I think omitting `{}` in short `if`, `for`, `foreach`,... brings you nothing then trouble. I would spent that additional 2 seconds to place them. In any case. I makes your code more proof against logic errors and more readable. Also I would explicitely declare every variable that I use. Good luck! ;) – hek2mgl Feb 05 '13 at 16:29
1

try

$bar = array();
foreach($foo as $n=>$ia)
   foreach($ia as $i=>$v)
      $bar[] = (object) array($n => $v);

this should give you:

$bar[0]->somefield = value1
$bar[1]->somefield = value2
$bar[2]->somefield = value3
$bar[3]->anotherfield = value1
$bar[4]->anotherfield = value2
$bar[5]->anotherfield = value3
galchen
  • 5,252
  • 3
  • 29
  • 43