I'm thinking that maybe this just needs a fresh set of eyes, but this is my first go at using session_set_save_handler() and storing session data in mysql so who knows, maybe I've really messed something up.

I've written this up according to a few examples I found online and based on my needs. DB_sessions is a singleton I use for connecting to the db (I know this isn't what's broken, I use it all of the time).

When I run it I get Fatal error: Exception thrown without a stack frame in Unknown on line 0. I think from what I'm seeing in my output page (bottom) and my database that the session variable is being written, but not via my session handler (because it echoes the session var, but the database is empty).

Here's my Session_handler class (I have some PDO error handling in there for now while it's not working)

<?php

if (! defined('EXT')){ exit('Invalid file request'); }

require_once('DB_sessions.php');

class Session_handler {
    protected $db = '' ;
    protected $life = '' ;

    public function __construct() {
        $this->life = get_cfg_var('session.gc_maxlifetime');

        session_set_save_handler( 
            array($this, '_open'),
            array($this, '_close'),
            array($this, '_read'),
            array($this, '_write'),
            array($this, '_destroy'),
            array($this, '_clean')
        );
    }

    public function _open() {
        $this->db = DB_sessions::get_instance();
        return true ;
    }

    public function _close() {
        $this->db = null ;
        return true ;
    }

    public function _read($id) {
        $expires = time();

        $sth = $this->db->prepare('SELECT data FROM sessions WHERE id_sessions = :id_sessions AND expires > :expires');
        $sth->bindParam(':id_sessions', $id, PDO::PARAM_STR);
        $sth->bindParam(':expires', $expires, PDO::PARAM_STR);

        if (!$sth->execute()) {
            echo "\nPDO::errorInfo():\n";
        print_r($sth->errorInfo());
            exit('<br/>read') ;
        }
        $row = $sth->fetch(PDO::FETCH_OBJ);
        $data = $row->data ;
        return $data ;
    }

    function _write($id, $data) {
        $expires = time() + $this->life ;

        $sth = $this->db->prepare('REPLACE INTO sessions VALUES id_sessions = :id_sessions, expires = :expires, data = :data');
        $sth->bindParam(':id_sessions', $id, PDO::PARAM_STR);
        $sth->bindParam(':expires', $expires, PDO::PARAM_STR);
        $sth->bindParam(':data', $data, PDO::PARAM_STR);

        if (!$sth->execute()) {
            echo "\nPDO::errorInfo():\n";
            print_r($sth->errorInfo());
            exit('<br/>write') ;
        }
        return true ;
    }

    function _destroy($id) {
        $db = DB_sessions::get_instance();
        $sth = $this->db->prepare('DELETE FROM sessions WHERE id_sessions = :id_sessions');
        $sth->bindParam(':id_sessions', $id, PDO::PARAM_STR);

        if (!$sth->execute()) {
            echo "\nPDO::errorInfo():\n";
            print_r($sth->errorInfo());
            exit('<br/>destroy') ;
        }
        return true ;
    }

    public function _clean() {
        $sth = $this->db->prepare('DELETE FROM sessions WHERE expires < UNIX_TIMESTAMP()');

        if (!$sth->execute()) {
            echo "\nPDO::errorInfo():\n";
            print_r($sth->errorInfo());
            exit('<br/>clean') ;
        }
        return true ;
    }

}
?>

and here's the script I'm running it from to test it...

<?php

define('EXT', '.' . pathinfo(__FILE__, PATHINFO_EXTENSION));

require_once('lib/Session_handler.php');

$sess = new Session_handler ;
session_start();

$_SESSION['data'] = 'testing';

echo $_SESSION['data'];

?>

Can anyone see what I am doing wrong, or even maybe offer some ideas as to what may throw that error?

As always, any help is greatly appreciated. Thanks in advance. Oh ya, I'm running on php 5.2.17.

Recommended Answers

All 3 Replies

Hi,

Did you try to initiate and instance of the db_session in the controller? Then just close the connection within the method that uses it.

!WARNING! These are just examples, others may have a different ways of doing things. However, If I am in your shoes, this is what I am going to do.

public function __construct(){

$this->db = DB_sessions::get_instance();

## add other stuffs here

}

You can also close the db connection within the methods, example for closing the connection within method.

public function _read($id) {

## all of your stuffs here



## just after the return or before it, add

self::_close();

## alternatively we can also use
$this->_close();

}

that's pretty much it from me...................................

what I meant by this

Did you try to initiate and instance of the db_session in the controller?

is

Did you try to initiate an instance of the db_session in the constructor?

the MVC question got stucked in my head..

@ veedeoo - hi, thanks for the suggestion! I did try your suggestion, but with no luck. I'm confused though, is session_set_save_handler() a special case? I mean, after I've created my Session_handler object my DB_sessions object is created, but only once (because it's in the constructor)... if I call my _close method within any of the other methods DB_sessions will be gone and nothing else will work... (which is exactly what happened - $this->db didn't exist anymore so it broke wherever a PDO prepared statement was called).

Oh ya, no worries, I understood what you meant! : )

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.