4

I came across some weird behavior in PHP:

function f($var) { // not using references
    foreach ($var as $k => $v) {
        unset($var[$k]); // shouldn't this unset from a copy?!
    }
}

print '<pre>';
var_dump($GLOBALS); // array
f($GLOBALS);
var_dump($GLOBALS); // null?!

http://3v4l.org/dQmQN

Anybody know why this is happening?

Karl Hill
  • 12,937
  • 5
  • 58
  • 95
nice ass
  • 16,471
  • 7
  • 50
  • 89

2 Answers2

3

Print out what it’s deleting and enable warnings to see what’s actually happening! =)

$GLOBALS contains GLOBALS. You unset it, which removes the actual global variable. If this were just pass-by-reference behaviour, you would get an empty array, not NULL.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • @ÁlvaroG.Vicario: Yep, still gets passed by reference. I will find out how PHP does it, but it would have to for the actual globals to be affected. That is why they are, though: http://codepad.viper-7.com/nzEbBN (Wow, that was a confusing paragraph in hindsight. `:P`) – Ry- May 09 '13 at 15:14
  • it looks like the GLOBALS variable only exists within itself [:)](http://www.youtube.com/watch?v=sf8FAqOQUq4) And if you remove it from itself, you remove it completely. Not sure why the reference from itself gets passed as a reference to GLOBALS and not as a reference to the copy though – nice ass May 09 '13 at 21:19
  • @OneTrickPony: `$GLOBALS` is a “live” “array” of the actual globals, so it will actually affect everything by `unset`ting elements or whatnot. Perhaps the reason it’s by reference is because it needs to act that way? Well, this is PHP. It doesn’t strictly need to make sense :) – Ry- May 09 '13 at 23:37
1

This happens because its the expected behavior:

This is a 'superglobal', or automatic global, variable. This simply means that it is available in all scopes throughout a script. There is no need to do global $variable; to access it within functions or methods.

Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • 1
    So $GLOBALS is always passed by reference, like objects? – nice ass May 09 '13 at 14:56
  • There is no "reference" in the traditional sense: its always in scope, is always global, there is only one copy of it. – Burhan Khalid May 09 '13 at 14:57
  • 1
    I don't think that explains the behaviour. He's not using the `$GLOBALS` identifier inside the function. He's supposedly operating on a copy. – Álvaro González May 09 '13 at 14:59
  • 2
    It's a bit more muddy. The variable name `GLOBALS` is a virtual entity in all local scopes. It's referenced to the PHP engines global array zval. But `$GLOBALS` can in fact be rebound to something different `$GLOBALS = new ArrayObject;` separating it from the actual global scope. But it's probably sensible to think of it as a reference. – mario May 09 '13 at 15:01
  • How's that? He didn't make a copy of it. $GLOBALS is a registry of all defined variables in the global scope. So I'm not sure what you were expecting it to do? That's why I quoted the reference in my answer; because its not a question of scope, its more a consequence of what actually is in $GLOBALS. – Burhan Khalid May 09 '13 at 15:01
  • This still doesn't adequately explain why unsetting all values *within* `$GLOBALS` unsets `$GLOBALS` itself. – deceze May 09 '13 at 16:12