问题
I'm using ADOdb. For some reason, the actual $db is not getting imported in the 'write' function.
The function is intended to import the $db's actual value. Instead, it's assigning an empty value to $db:
<?php
// load ADODB class
include(DIR_WS_CLASSES . "adodb5/adodb.inc.php");
$db = NewADOConnection(DB_TYPE);
$db->Connect(DB_SERVER, DB_SERVER_USERNAME, DB_SERVER_PASSWORD, DB_DATABASE);
class SessionManager {
var $life_time;
function SessionManager(){
global $db;
// Read the maxlifetime setting from PHP
$this->life_time = get_cfg_var("session.gc_maxlifetime");
// Register this object as the session handler
session_set_save_handler(array(&$this, "open"),
array(&$this, "close"),
array(&$this, "read"),
array(&$this, "write"),
array(&$this, "destroy"),
array(&$this, "gc"));
}
function open($save_path, $session_name){
global $sess_save_path;
global $db;
$sess_save_path = $save_path;
return true;
}
function close(){
global $db;
return true;
}
function read($id){
global $db;
// Set empty result
$data = '';
// Fetch session data from the selected database
$time = time();
$newid = $db->qstr($id, get_magic_quotes_gpc());
$sql = "SELECT session_data
FROM sessions
WHERE session_id = $newid
AND expires > $time";
$rs = $db->Execute($sql) or die($db->ErrorMsg());
$a = $rs->RecordCount();
if($a > 0){
$data = $rs->fields['session_data'];
}
return $data;
}
function write($id, $data){
global $db;
// Build query
$time = time() + $this->life_time;
$newid = $db->qstr($id, get_magic_quotes_gpc());
$newdata = $db->qstr($data, get_magic_quotes_gpc());
$sql = "REPLACE sessions
(session_id, session_data, expires)
VALUES($newid, $newdata, $time)";
$rs = $db->Execute($sql) or die($db->ErrorMsg());
return TRUE;
}
function destroy($id){
global $db;
// Build query
$newid = $db->qstr($id, get_magic_quotes_gpc());
$sql = "DELETE FROM sessions
WHERE session_id = $newid";
$db->Execute($sql) or die($db->ErrorMsg());
return TRUE;
}
function gc(){
// Garbage Collection
global $db;
// Build DELETE query. Delete all records that passed expiration time
$sql = "DELETE FROM sessions
WHERE expires < UNIX_TIMESTAMP()";
$db->Execute($sql) or die($db->ErrorMsg());
// Always return TRUE
return true;
}
}
// initialize session
$sess = new SessionManager();
session_start();
?>
Why is the actual $db not imported in the 'write' function?
How can I fix the problem?
回答1:
EDITED FOR THOSE WHO DIDN'T FOLLOW THE COMMENTS ;)
"As of PHP 5.0.5 the write and close handlers are called after object destruction and therefore cannot use objects or throw exceptions. The object destructors can however use sessions. It is possible to call session_write_close() from the destructor to solve this chicken and egg problem"
So the idea is to have a destructor like this:
function __destruct() {
session_write_close();
}
So that objects can be used in the write & close handlers.
Then, for safety, to re-instantiate $db in write & close because the global $db destructor may very well be called before the SessionHandler one.
回答2:
Either you don't assign $db as global or you assign it an empty value.
回答3:
I'm not a PHP expert but maybe you're overwriting it. Try an echo of $db before and after
global $db;
And: are you sure you assigned anything to $db (before looking to its value inside the function)?
回答4:
Try var_dump on $db outside and inside the function.
回答5:
I am pretty sure what is the problem. See your code will work fine when this file was included in global scope. But consider this:
$a=1;
function displaya()
{
global $a;
var_dump($a);
}
When you run this file you will see int(1) as the output.
But consider another file:
function abc()
{
include("above-stated-file.php");
displaya();
}
abc();
Now it will display NULL.
The reason is that in second file. Your first file was included in a local context, not the global one. Thats why global $a doesn't work.
Change it to:
$GLOBALS['a']=....;
and when you use it: $a=$GLOBALS['a'];
回答6:
Try these 2 things:
Assign
$GLOBALS['db']=...;instead of
$db=...;in your global script. Then reference it in your function as
$db=$GLOBALS['db'];.Reason: It's a possibility that you are assigning
$dbin some place which is not global.Make it as private property of your class. Provide a getter, but not the setter. Instead set it from your constructor.
回答7:
You dont seem initialise $db anywhere in the above code.
I would expect to see a $db = new ADO("myserver,mydb,user,password") call somewhere
in the code.
来源:https://stackoverflow.com/questions/1453143/php-global-variable-not-being-imported-into-session-handler