Глобальная переменная PHP не импортируется в обработчик сеанса - PullRequest
0 голосов
/ 21 сентября 2009

Я использую ADOdb. По какой-то причине фактический $db не импортируется в функцию записи.

Функция предназначена для импорта фактического значения $db. Вместо этого он присваивает пустое значение $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();
?>

Почему фактический $db не импортируется в функцию записи?

Как я могу решить проблему?

Ответы [ 7 ]

5 голосов
/ 21 сентября 2009

РЕДАКТИРОВАНИЕ ДЛЯ ТОГО, КОТОРЫЙ НЕ СЛЕДОВАЛ ЗА КОММЕНТАРИИ;)

"Начиная с PHP 5.0.5, обработчики записи и закрытия вызываются после уничтожения объекта и, следовательно, не могут использовать объекты или генерировать исключения. Однако деструкторы объекта могут использовать сеансы. Для решения проблемы можно вызвать session_write_close () из деструктора. это проблема курицы и яйца "

Итак, идея в том, чтобы иметь такой деструктор:

function __destruct() {
    session_write_close();
}

Чтобы объекты могли использоваться в обработчиках записи и закрытия.

Затем, в целях безопасности, создать экземпляр $ db при записи и закрытии, потому что глобальный деструктор $ db вполне может быть вызван перед SessionHandler.

0 голосов
/ 21 сентября 2009

Я почти уверен, в чем проблема. Смотрите, ваш код будет работать нормально, когда этот файл был включен в глобальную область Но учтите это:

$a=1;
function displaya()
{
    global $a;
    var_dump($a);
}

Когда вы запустите этот файл, вы увидите int(1) в качестве вывода.

Но рассмотрим другой файл:

function abc()
{
include("above-stated-file.php");
displaya();
}

abc();

Теперь будет отображаться NULL.

Причина в том, что во втором файле. Ваш первый файл был включен в локальный контекст, а не в глобальный. Вот почему global $a не работает.

Измените его на:

$GLOBALS['a']=....;

и при его использовании: $a=$GLOBALS['a'];

0 голосов
/ 21 сентября 2009

Попробуйте эти 2 вещи:

  1. Назначить

    $GLOBALS['db']=...;
    

    вместо

    $db=...;
    

    в вашем глобальном скрипте. Затем укажите его в вашей функции как $db=$GLOBALS['db'];.

    Причина : Возможно, вы назначаете $db в каком-то месте, которое не является глобальным.

  2. Сделайте это частной собственностью вашего класса. Предоставить получатель, но не установщик. Вместо этого установите его из вашего конструктора.

0 голосов
/ 21 сентября 2009

Вы, кажется, не инициализируете $db где-либо в приведенном выше коде.

Я бы ожидал увидеть где-нибудь $db = new ADO("myserver,mydb,user,password") звонок в коде.

0 голосов
/ 21 сентября 2009

Попробуйте var_dump на $ db снаружи и внутри функции.

0 голосов
/ 21 сентября 2009

Я не эксперт по PHP, но, возможно, вы перезаписываете его. Попробуйте эхо $ db до и после

global $ db;

И: вы уверены, что что-то присвоили $ db (прежде чем искать его значение внутри функции)?

0 голосов
/ 21 сентября 2009

Либо вы не присваиваете $db как глобальное, либо присваиваете ему пустое значение.

...