PHP Global variable not being imported into session handler

无人久伴 提交于 2019-12-11 20:58:45

问题


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:

  1. 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 $db in some place which is not global.

  2. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!