PHP var_dump and loop giving different results

2019-08-23 14:18发布

问题:

I have the following code:

var_dump($cursor);
foreach($cursor as $obj) {
    echo "<div class='item' id='" . $obj['_id'] . "'>";
        echo "<span class='listnick'>" . $obj['nick'] . "</span>";
    echo "</div>";
}

The result of var_dump is the following:

array(2) {
  [0]=>
  &array(9) {
    ["_id"]=>
    object(MongoId)#9 (1) {
      ["$id"]=>
      string(24) "50af8dcd9cc231534400000c"
    }

    ["nick"]=>
    string(6) "safari"

  }
  [1]=>
  array(9) {
    ["_id"]=>
    object(MongoId)#8 (1) {
      ["$id"]=>
      string(24) "50af8dca9cc2315644000009"
    }
    ["nick"]=>
    string(6) "chrome"
  }
}

so obviously the foreach should print out "safari" and "chrome", but the problem is really weird:

Sometimes it returns "safari" twice and omits "chrome", and viceversa for the other client. I tried putting the var_dump and the foreach loop near to be sure they are the SAME and there are no changes in the object between the two commands, but really I got no idea what's going on.

Any help? Thanks in advance.

回答1:

Notice how safari is a reference to an array: &array.

This might result from having a foreach where $obj is a reference:

foreach($cursor as &$obj) {
   ..
}
//unset($obj);

In PHP, the scope of $obj does not end with execution of the loop, so you should do an unset whenever you looped using a reference.

This might also result from using the reference assignment somewhere:

$cursor[] =& $safari;


回答2:

This are 2 difference codes ... One is using & reference which would modify the array output and the other is not

array(2) {
  [0]=>
  &array(9) {
  ^----------------------------- Reference sign 
    ["_id"]=>
    object(MongoId)#9 (1) {
      ["$id"]=>
      string(24) "50af8dcd9cc231534400000c"
    }

    ["nick"]=>
    string(6) "safari"

  }

Topical example of what happened

$a = $b = array(array("_id" => new MongoId(),"nick" => "chrome"));

foreach ( $a as $k => &$v )
    $k == "nick" and $v['nick'] = "Safari";

foreach ( $b as $k => $v )
    $k == "nick" and $v['nick'] = "Safari";

var_dump($a);
var_dump($b);

Output

array (size=1)
  0 => 
    &array (size=2)
      '_id' => 
        object(MongoId)[1]
          public '$id' => string '50af93a2a5d4ff5015000011' (length=24)
      'nick' => string 'Safari' (length=6) <------ changed

array (size=1)
  0 => 
    array (size=2)
      '_id' => 
        object(MongoId)[2]
          public '$id' => string '50af93a2a5d4ff5015000012' (length=24)
      'nick' => string 'chrome' (length=6) <------- not changed 

Can you see that one if the Nick is modified not the two