Search code examples
phpwarningsstrict

PHP 5.4 code update - Creating default object from empty value warnings in foreach and objects array


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?


Solution

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