1 (edited by FSX 2008-04-03 08:45)

Topic: Save session in database

I'm trying to save sessions in my database, but it isn't working. I followed this guide: http://shiflett.org/articles/storing-se … a-database.

I'm using a database object/class (similiar to punbb's one) to write to the database, but all objects are destroyed before write is called. Check the first warning block: http://nl.php.net/manual/nl/function.se … andler.php. I don't really know how to solve it.

This are my session functions:

/* Session functions
---------------------------------------------------------------------------------------------*/

function start_session($db_save=true,$save_path=false)
{
    // Save session in specified path or database
    if ($save_path !== false)
    {
        ini_set('session.save_path',$save_path);
    }
    else if ($db_save === true)
    {
        session_set_save_handler(
            '_open',
            '_close',
            '_read',
            '_write',
            '_destroy',
            '_clean'
        );
    }

    // Start the session
    session_start();
    
    // Regenerate session id if $_SESSION['initiated'] isn't set
    if (!isset($_SESSION['initiated']))
    {
        session_regenerate_id();
        $_SESSION['initiated'] = true;
    }
    
    // Generate a token if there isn't one
    if (!isset($_SESSION['token']))
        $_SESSION['token'] = sha1(md5(uniqid(rand(),true).$_SERVER['HTTP_USER_AGENT']));
}

function _open()
{
    return true;
}

function _close()
{
    return true;
}

function _read($id)
{
    global $db;
 
    if ($result = $db->query('SELECT data FROM %prefix%sessions WHERE id=\''.$db->escape($id).'\''))
    {
        if ($db->num_rows($result))
        {
            $row = $db->fetch($result);
 
            return $row['data'];
        }
    }
 
    return '';
}

function _write($id,$data)
{
    global $db;
 
    return $db->query('REPLACE INTO %prefix%sessions VALUES (\''.$db->escape($id).'\',\''.$db->escape(time()).'\',\''.$db->escape($data).'\')');
}

function _destroy($id)
{
    global $db;
 
    return $db->query('DELETE FROM %prefix%sessions WHERE id=\''.$db->escape($id).'\'');
}

function _clean($max)
{
    global $db;
    
    $old = time() - $max;
 
    return $db->query('DELETE FROM %prefix%sessions WHERE access < \''.$db->escape($old).'\'');
}

And I use the first function (start_session(true);) to start it.

Can someone help me to solve this?

Re: Save session in database

The page you linked to wrote:

Warning

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 put a call to session_write_close in the destructor and you're good to go?

3 (edited by FSX 2008-04-03 12:41)

Re: Save session in database

I tried, but it didn't work. I still got this error: Fatal error: Call to a member function query() on a non-object in C:\wosportable\www\WMS\include\functions.php on line 212. And sessions aren't working.

This is the deconstrutor of my database class:

    function __deconstruct()
    {
        if ($this->link)
        {
            if ($this->query_result)
                @mysqli_free_result($this->query_result);

            return @mysqli_close($this->link);
        }
        else
        {
            return false;
        }
    }

I putted session_write_close(); in there, but it didn't work.

EDIT:
I putted session_write_close(); in my footer.php and I don't get the error anymore, but the sessions arent working. I checked the sessions table and it contains a session. I think something is wrong with the _read function.

EDIT 2:
Sessions are working. Only my login script doesn't work.

EDIT 3:
It seems that I have to call session_write_close(); after each session edit.

Something like this, my logout:

else if ($g_action == 'logout' && checkToken()) 
{
    unset($_SESSION['user']);
    session_write_close();
    header('location: user.php');
    exit;
}