PHP language article

Home >> PHP language >>

  Storing PHP sessions in a database

This article will explain how to Store PHP Sessions in a Database. Basically, we can store session in a file or database.

Why is it good save to save sessions in the database?

The primary difference is that fetching the session info from a database can be quite a bit faster than from a file system. This is partly because of DB caching, but also because if there are large numbers of sessions files the file system may not cope well with it. Most file systems start to degrade when there are a few thousand files in a single directory, whereas DBs don't run into this problem.

If you only have a few sessions it doesn't matter, but when there are 10,000 or 10,000,000 sessions it definitely does.

Saving session data into database.

Before you can store sessions in a database, you need to create a table. The following example demonstrates the CREATE syntax for such a table:

CREATE TABLE IF NOT EXISTS `session_storage` (
  `session_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT 'session id',
  `session_expires` datetime NOT NULL COMMENT 'session expire time',
  `session_data` text COLLATE utf8_unicode_ci COMMENT 'serialized session data',
  PRIMARY KEY (`session_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Now that you have a table to store the sessions in, you can learn how to do it.

session_set_save_handler()

The function is called session_set_save_handler(), and it takes six arguments, each of which is the name of a function that you write. These functions are responsible for the following tasks:

1. Opening the session data store.
2. Closing the session data store.
3. Reading session data.
4. Writing session data.
5. Destroying all session data.
6. Cleaning out old session data.

For explaining purpose, I assume that this function is called as follows:

session_set_save_handler('open',  'close',  'read',  'write',  'destroy',  'gc');

Note: You must call session_set_save_handler() prior to calling session_start(), but you can define the functions themselves anywhere.

open(string $savePath, string $sessionName)
The open callback works like a constructor in classes and is executed when the session is being opened. It is the first callback function executed when the session is started automatically or manually with session_start(). Return value is TRUE for success, FALSE for failure.

close()
The close callback works like a destructor in classes and is executed after the session write callback has been called. It is also invoked when session_write_close() is called. Return value should be TRUE for success, FALSE for failure.

read(string $sessionId)
The read callback must always return a session encoded (serialized) string, or an empty string if there is no data to read.

This callback is called internally by PHP when the session starts or when session_start() is called. Before this callback is invoked PHP will invoke the open callback.

The value this callback returns must be in exactly the same serialized format that was originally passed for storage to the write callback. The value returned will be unserialized automatically by PHP and used to populate the $_SESSION superglobal.

write(string $sessionId, string $data)
The write callback is called when the session needs to be saved and closed. This callback receives the current session ID a serialized version the $_SESSION superglobal. The serialization method used internally by PHP is specified in the session.serialize_handler ini setting.

The serialized session data passed to this callback should be stored against the passed session ID. When retrieving this data, the read callback must return the exact value that was originally passed to the write callback.

destroy($sessionId)
This callback is executed when a session is destroyed with session_destroy() or with session_regenerate_id() with the destroy parameter set to TRUE. Return value should be TRUE for success, FALSE for failure.

gc($lifetime)
The garbage collector callback is invoked internally by PHP periodically in order to purge old session data. The value of lifetime, which is passed to this callback can be set in session.gc_maxlifetime. Return value should be TRUE for success, FALSE for failure.

Now main coding part will start here, We have an SessionHandlerInterface  predefined Interface in php.

SessionHandlerInterface is an interface which defines a prototype for creating a custom session handler. In order to pass a custom session handler to session_set_save_handler() using its OOP invocation, the class must implement this interface.

Now we need to implement this Interface using our Class, let's explain it through an example.

<?php
//File : session.class.php

class ManageSession implements SessionHandlerInterface
{

    private $link;

    /**
     * @It executed when the session is started automatically or manually with session_start()
     * @param type $savePath
     * @param type $sessionName
     * @return boolean
     */
    public function open($savePath, $sessionName)
    {
        $link = mysqli_connect("server","user-name","password","database-name");
        if ($link) {
            $this->link = $link;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @It is also invoked when session_write_close() is called.
     * @return boolean
     */
    public function close()
    {
        mysqli_close($this->link);
        return true;
    }

    /**
     * @It must always return a session encoded (serialized) string, 
     * - or an empty string if there is no data to read.
     * @param type $id
     * @return string
     */
    public function read($id)
    {
        $result = mysqli_query($this->link, "SELECT session_data FROM session_storage "
                . "WHERE session_id = '$id' AND session_expires > '" . date('Y-m-d H:i:s') . "' ");

        if ($row = mysqli_fetch_assoc($result)) {
            return $row['session_data'];
        } else {
            return "";
        }
    }

    /**
     * @It will called when the session needs to be saved and closed.
     * @param type $id
     * @param type $data
     * @return boolean
     */
    public function write($id, $data)
    {
        $DateTime = date('Y-m-d H:i:s');
        $NewDateTime = date('Y-m-d H:i:s', strtotime($DateTime . ' + 1 hour'));
        $result = mysqli_query($this->link, "REPLACE INTO session_storage SET "
                . "session_id = '$id', session_expires = '$NewDateTime', session_data = '$data' ");

        if ($result) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @It will executed when a session is destroyed with session_destroy() 
     * - or with session_regenerate_id() with the destroy parameter set to TRUE
     * @param type $id
     * @return boolean
     */
    public function destroy($id)
    {
        $result = mysqli_query($this->link, "DELETE FROM session_storage WHERE session_id = '$id' ");
        if ($result) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @It will invoked internally by PHP periodically in order to purge old session data
     * @param type $maxlifetime
     * @return boolean
     */
    public function gc($maxlifetime)
    {
        $result = mysqli_query($this->link, "DELETE FROM session_storage "
                . "WHERE ((UNIX_TIMESTAMP(session_expires) + '$maxlifetime') < '$maxlifetime') ");

        if ($result) {
            return true;
        } else {
            return false;
        }
    }

}

$handler = new ManageSession();
session_set_save_handler($handler, true);

?>

Register some session variables.

<?php
// File : check_session_one.php

require_once('session.class.php');

// Start the session
session_start();

// Set session variables
$_SESSION["name"] = "phpcodehub";
$_SESSION["php"] = "Hypertext Preprocessor";

?>

Get session registered variable's value

<?php
// File : check_session_two.php

require_once('session.class.php');

// Start the session
session_start();

// Retrieve session variables
if (isset($_SESSION["name"])) {
    echo $_SESSION["name"] . "<br/>";
} else {
    echo "Session 'name' not registered." . "<br/>";
}

// Retrieve session variable 'php'
if (isset($_SESSION["php"])) {
    echo $_SESSION["php"] . "<br/>";
} else {
    echo "Session 'php' not registered." . "<br/>";
}

?>

Note : 
1.
In 'ManageSession' class we have written code to save session data in the database and retrieve it from the database.
2. In 'check_session_one.php' file we have written code to register some session variable.
3. In 'check_session_two.php' you can see all session registered variable's value in this file.

How to run these files.
Spet 1: You need to navigate from your server and open 'check_session_one.php' file.
Step 2: To see the session values, navigate from your server and open 'check_session_one.php' file.

Finally, you will see the output like below.

phpcodehub
Hypertext Preprocessor

Congratulation, now you can save the session data in the database, download the code (source code & SQL dump) and try to run in your system.

  Download code

Comments

nice explanation

nice explanation

  1 year ago      Amit Kumar      
SessionHandlerInterface

Is SessionHandlerInterface predefined in PHP ?

  1 year ago      Amit Kumar      
Yes it is predefined in PHP.
Re : SessionHandlerInterface.

Yes, You can check the synopsis of this interface below.

interface SessionHandlerInterface
{
          abstract public bool close ( void )
          abstract public bool destroy ( string $session_id )
          abstract public bool gc ( int $maxlifetime )
          abstract public bool open ( string $save_path , string $session_name )
          abstract public string read ( string $session_id )
          abstract public bool write ( string $session_id , string $session_data )
}

  1 year ago      phpcodehub      
Thanks
Re : Yes it is predefined in PHP..

Thanks a lot phpcodehub

  1 year ago      Amit Kumar      

Write your comment now