Creeping towards PHP — global tricked me

global tricked me
Testing environment:
php 4.3.11
Smarttemplate 1.0.2 02.04.2003 
While adding the file inclusion support for Smarttemplate, I found it problematic to use multiple Smarttemplate in a sigle PHP script.

With the help of almighty Google, I knew a way to solve this problem.
Locate the output method of class Smarttemplate(in file class.smarttemplate.php), change the last line
unset($_top);
into
unset($GLOBALS[‘_top’]);
and all will work!

But why this happens? Notice that the first line of function output is
global $_top;
which introduces the global varibale $_top into the local scope and having
unset($_top);
al last seems reasonable at all. Why bother with $GLOBALS?
Try adding
var_dump($_top);
after
$page->output();
//$page is your instance of Smarttemplate
and you’ll see all contents in $_top dumped indicating that the unset($_top); at the bottom of the output method does not work as expected at all!

The problem lies in the way PHP processes global statement and the unset() function.
Here I quote a comment found in the PHP manual:
cellog at users dot sourceforge dot net (22-May-2002 12:02)

comment on april 9 regarding:
function foo ()
{
  global $testvar;
  $localvar = new Object ();
  $testvar = &$localvar;
}
The reason this doesn’t work is that when you use & to assign to $testvar, it reassigns $testvar to point at what $localvar points at.
$testvar = $localvar should work as well as $GLOBALS[‘testvar’] = &$localvar, although instance data will be copied and any references to parent classes will be broken.  I hate that :).
In other words, the declaration "global $testvar;" is telling php "make $testvar point at the same location as $GLOBALS[‘testvar’]" but "$testvar = &$localvar" tells php "make $testvar point at the same location as $localvar"!!!

Clear enough, isn’t it?
To be even more clear let’s see the following script:
———source file———-
<?php
$msg = "I’m in the global scope!";
test();
function test() {
    global $msg;
    /*now we have a new local variable $msg
      which is not the same one as that in the global scope
      but points at the same location as the $msg in the global scope
     */
    unset($msg);
    //now the local $msg in unset, but the $msg in the global scope
    //is still there!
    echo $GLOBALS[‘msg’];
}
?>
———output———-
I’m in the global scope!

We can conclude that unset() here did not actually destroy the content of the varible to which the local $msg is bound.
According to the PHP manual, if a variable that is PASSED BY REFERENCE is unset() inside of a function, only the local variable is destroyed. The variable in the calling environment will retain the same value as before unset() was called.
So what global does is make the local $msg a reference to the global $msg.

Conclusions:
global $var; produces a local $var and make it a reference to the $var in global scope.
unsetting a reference won’t destroy the actual content of the varible being referenced.
Be clear about what you are unsetting, the reference or the actual variable?

Advertisements
This entry was posted in PHP Rocks. Bookmark the permalink.

2 Responses to Creeping towards PHP — global tricked me

  1. Unknown says:

    wow gold!All wow gold US Server 24.99$/1000G on sell! Cheap wow gold,wow gold,wow gold,Buy Cheapest/Safe/Fast WoW US EU wow gold Power leveling wow gold from the time you wWorld of Warcraft gold ordered!

    wow power leveling wow power leveling power leveling wow power leveling wow powerleveling wow power levelingcheap wow power leveling wow power leveling buy wow power leveling wow power leveling buy power leveling wow power leveling cheap power leveling wow power leveling wow power leveling wow power leveling wow powerleveling wow power leveling power leveling wow power leveling wow powerleveling wow power leveling buy rolex cheap rolex wow gold wow gold wow gold wow gold -209891301741494

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s