Question

I would like know if this is possible to supplant $_SESSION. I would like to create a system that uses $ _SESSION to record my sessions in my database, like this:

$_SESSION['identifier'] = 'value'; // Perform insert/update on my DBMS
echo $_SESSION['identifier']; // Perform select on my DBMS

I would like my system is completely transparent and functional if my class session is unavailable or disabled by the site administrator.

Thank you for your help.

Was it helpful?

Solution

Here is a sample code:

$sess = new sess();

session_start();
$_SESSION =& $sess;

//test
$_SESSION['value'] = 'ccc';

some_test_func();
function some_test_func() {
//test again in different scope
$_SESSION['anotehr_value'] = 444;
}


class sess implements \Iterator, \ArrayAccess, \Countable
{

    protected $session_data;

    public final function rewind() {
        reset($this->session_data);
    }

    public final function current() {
        $var = current($this->session_data);
        return $var;
    }

    public final function key() {
        $var = key($this->session_data);
        return $var;
    }

    public final function next() {
        $var = next($this->session_data);
        return $var;
    }

    public final function valid() {
        $var = $this->current() !== false;
        return $var;
    }

    public final function offsetExists($offset) {
        //Database query comes here (SELECT)
        print 'SELECT var_value FROM session_data WHERE var_name = :offset AND session_id = :session_id';
        $session_id = session_id();
        return isset($this->session_data[$offset]);
    }

    public final function offsetGet($offset) {
        //Database query comes here (SELECT)
        print 'SELECT var_value FROM session_data WHERE var_name = :offset AND session_id = :session_id';
        $session_id = session_id();
        return $this->session_data[$offset];
    }

    public final function offsetSet($offset,$value) {
        //Database query comes here (REPLACE by primary key)
        print 'REPLACE INTO session_data (session_id, var_name, var_value) VALUES (:session_id, :offset, :value)';
        $session_id = session_id();
        $this->session_data[$offset] = $value;
    }

    public final function offsetUnset($offset) {
        //Database query comes here (DELETE)
        print 'DELETE FROM session_data WHERE var_name = :offset AND session_id = :session_id';
        $session_id = session_id();
        unset($this->session_data[$offset]);
    }

    public final function count() {
        return count($this->session_data);
    }
}

You can extend it by adding also overloading. You can use $session_data as cached copy or use all queries (which if you can you should avoid). In the general case I would recommend not to do a query against every session change (there will be a lot of DB writes). Maybe you are doing this in order to avoid overwriting sessions but for this you could use a locking mechanism to serialize all request with the same session_id. The other reason I would avoid this because this line: $_SESSION =& $sess; might not work in some future PHP version. (I tested this on php 5.3.20).

Another issue is that some other person in future might just use your code not even suspecting what $_SESSION is doing on the background... You should explicitly document this behaviour.

P.S. or maybe you are just looking to store the sessions in the database. Then you should look at http://php.net/manual/en/function.session-set-save-handler.php Here you could get away with only two queries - on session read and on session write.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top