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?
DebbieThe only difference I know of has to do with the fact that in PHP5 "global" now functions in terms of references, and objects are now passed by reference by default instead of copied. So you may be running into something similar to what is described toward the end of the global page (under the "References with global and static variables" heading). But this is mostly speculation on my part as the code you provided doesn't really show where (and how) the object is originally instantiated, nor how the two functions are actually interrelated.
That being said, it sounds like yet another good reason to avoid using globals, some others being the maintenance headaches they can cause and the close-coupling they create which makes it difficult to re-use code.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.
DebbieWhy not give your function a database object?
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?
DebbieThe only difference I know of has to do with the fact that in PHP5 "global" now functions in terms of references, and objects are now passed by reference by default instead of copied. So you may be running into something similar to what is described toward the end of the global page (under the "References with global and static variables" heading). But this is mostly speculation on my part as the code you provided doesn't really show where (and how) the object is originally instantiated, nor how the two functions are actually interrelated.
That being said, it sounds like yet another good reason to avoid using globals, some others being the maintenance headaches they can cause and the close-coupling they create which makes it difficult to re-use code.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.
DebbieWhy not give your function a database object?