The_Unknown
The_Unknown

Reputation: 1048

Referenced array iteration in php results in strange result

I have seen strange behavior that I don't quite get. I do the following:

$array = [
    'a' => [
        'a1' => [
            'a11' => 1,
            'a12' => 2
        ],
        'a2' => [
            'a21' => 3,
            'a22' => 4
        ],
    ],
    'b' => [
        'b1' => [
            'b11' => 1,
            'b12' => 2
        ],
        'b2' => [
            'b21' => 3,
            'b22' => 4
        ],
    ],
];

foreach ($array as $strLevel1 => &$arrLevel1)
{
    foreach ($arrLevel1 as $strLevel2 => &$arrLevel2)
    {
        foreach ($arrLevel2 as $strLevel3 => &$varLevel3)
        {
            $varLevel3 = 0;
        }
    }
}

echo '<pre>';
var_dump($array);
echo '</pre>';

foreach ($array as $strLevel1 => $arrLevel1)
{
}

echo '<pre>';
var_dump($array);
echo '</pre>';

The result is as follows:

array(2) {
  ["a"]=>
  array(2) {
    ["a1"]=>
    array(2) {
      ["a11"]=>
      int(0)
      ["a12"]=>
      int(0)
    }
    ["a2"]=>
    array(2) {
      ["a21"]=>
      int(0)
      ["a22"]=>
      int(0)
    }
  }
  ["b"]=>
  &array(2) {
    ["b1"]=>
    array(2) {
      ["b11"]=>
      int(0)
      ["b12"]=>
      int(0)
    }
    ["b2"]=>
    &array(2) {
      ["b21"]=>
      int(0)
      ["b22"]=>
      &int(0)
    }
  }
}
array(2) {
  ["a"]=>
  array(2) {
    ["a1"]=>
    array(2) {
      ["a11"]=>
      int(0)
      ["a12"]=>
      int(0)
    }
    ["a2"]=>
    array(2) {
      ["a21"]=>
      int(0)
      ["a22"]=>
      int(0)
    }
  }
  ["b"]=>
  &array(2) {
    ["a1"]=>
    array(2) {
      ["a11"]=>
      int(0)
      ["a12"]=>
      int(0)
    }
    ["a2"]=>
    array(2) {
      ["a21"]=>
      int(0)
      ["a22"]=>
      int(0)
    }
  }
}

As you can see, in the first output everything is ok. But in the second one, the b-named branch of the array is replaced by the a-named branch. This is because of the referencing I did. If I put a "&" before $arrLevel1 in the last loop, it works again.

Why is that? Am I doing something wrong with the references? Or should I don't use them at all and do array manipulation only fully qualified without any reference?

Thanks in advance.

Upvotes: 0

Views: 22

Answers (1)

Philipp
Philipp

Reputation: 15629

Maybe you should unset the reference to $arrLevel1 after your loop, till you reused the var for the second loop.

foreach ($array as $strLevel1 => &$arrLevel1)
{
    foreach ($arrLevel1 as $strLevel2 => &$arrLevel2)
    {
        foreach ($arrLevel2 as $strLevel3 => &$varLevel3)
        {
            $varLevel3 = 0;
        }
    }
}

// remove reference
unset($arrLevel1);

echo '<pre>';
var_dump($array);
echo '</pre>';

foreach ($array as $strLevel1 => $arrLevel1)
{
}

echo '<pre>';
var_dump($array);
echo '</pre>';

A way to come around unset is to use unique names for your loop variables or - if you want to loop over the same array again - just also use an reference loop var.

foreach ($array as $strLevel1 => &$arrLevel1)
{
    foreach ($arrLevel1 as $strLevel2 => &$arrLevel2)
    {
        foreach ($arrLevel2 as $strLevel3 => &$varLevel3)
        {
            $varLevel3 = 0;
        }
    }
}

// also use a reference
foreach ($array as $strLevel1 => &$arrLevel1)
{
}

Most of the time, it might be simplier to just don't use references or move the loop in an "atomic" function which just does the manipulation and returns the result.

Upvotes: 1

Related Questions