Click to See Complete Forum and Search --> : Global doesn't work properly in PHP 5


Debbie-Leigh
February 3rd, 2008, 01:50 PM
Hi,

My websites have just been moved to a new server with PHP 5 on it and it seems the the global statement has changed it's behaviour slightly.

I have a set of functions which control the session reading and writing. They've been working fine on php 4 for several years now, but in PHP 5 they seem to be having a problem globalising the database object at the end of processing.

After much testing, I discovered that if I globalise the object in the last function to be executed (i.e. the one with the exit statement), then there is no problem. This seems rather odd to me, as I thought that the whole point of the global statement is that you can globalise variables from anywhere. I wouldn't have thought that you should have to globalise them all the way back up the call tree, just to be able to use them in the function at the bottom of the tree. So, I'm a little confused and would like some advice.

My functions are:

funEnd {
do some stuff;
exit();
}

the session function:

function funSessRead($strKey) {
// Read a session from the database

global $dbSite;

$qsSession = $dbSite->runQuery("SELECT value FROM " . TBLSITE_SESSION . " WHERE session_id = '" . $strKey . "' AND expiry > '" . time() . "'");
if ($qsSession):
$rsSession = $dbSite->fetchArray();
return $rsSession["value"];
else:
return "";
endif;
}


In this setup, $dbSite->runQuery produces the error: "Fatal error: Call to a member function runQuery() on a non-object". The only way I've found to make it work is to globalise $dbSite in funEnd as well, like this:

funEnd {
global $dbSite;
do some stuff;
exit();
}


Does anyone know whether this is just a bug in PHP5 and whether there is a way to stop the new behaviour?

Debbie

PeejAvery
February 3rd, 2008, 05:29 PM
The difference is not in PHP4 vs. PHP5, it is in the php.ini configuration file. Since it is best to not register every variable as a global in order to save on resources, the configuration for register_globals is default to Off. In PHP4, it is defaulted to On.

So, the best way is to have it turned off, and then call all variables as global within the function. This is the most resourceful way. Hence why your last code example works.

Debbie-Leigh
February 3rd, 2008, 06:26 PM
Hi PeejAvery,

I've just checked and register_globals is on. I do understand your reasoning, but the control of this is in my hoster's hands.

However, the problem is that using global as you describe (which is always how and why I've used it) doesn't seem to work anymore in my example, without globalising it in the function that calls exit(). The database object seems to have been lost by the time the session tidy up happens, but in PHP4, the object still existed, so the session function could still use the existing database connection.

Which makes me think that PHP5 has had it's object clean up routine moved to happen earlier, perhaps before the session clean up happens.

Can you or anyone confirm whether this is the case?

Debbie

PeejAvery
February 3rd, 2008, 09:19 PM
I think you misunderstood my last comment, or I misunderstood your most recent one. I have always, in PHP 5, had to call global $variable in every function in order to access a variable not created by the function. That is something I just started doing as soon as I upgraded from PHP almost 2 years ago.

Debbie-Leigh
February 5th, 2008, 07:54 PM
Hi,

FYI, for anyone with a similar problem. Rather than spending any more time trying to pinpoint what was looking to be one of those really obscure problems, I solved this problem by creating another link to the database within the session function, so it doesn't need to rely on the previously declared database object being available.

So my function now looks like:

function funSessRead($strKey) {
// Read a session from the database

@require(INC_CONFIG_DB_SITE);

$qsSession = $dbSite->runQuery("SELECT value FROM " . TBLSITE_SESSION . " WHERE session_id = '" . $strKey . "' AND expiry > '" . time() . "'");
if ($qsSession):
$rsSession = $dbSite->fetchArray();
return $rsSession["value"];
else:
return "";
endif;
}

The require calls in the script that sets up a database connection and assigns it to $dbSite which will be isolated within this function, so it won't affect anything outside that uses the other $dbSite object.

Debbie