Save PHP Sessions to Database

PUBLISHED ON MAY 15, 2020 — CODE, HOW-TO, PHP

In a previous post I wrote about wpengine and their issue with sessions I found a “workaround” for this.

DISCLAIMER: I’m not saying this is the best or the only solution but this is the one I was able to find and make it work in my case. You can modify to your needs and check the references at the end of the document.

Let’s create a database or table. I am storing sessions in another database.

CREATE DATABASE `wp_sessions`;

CREATE TABLE `sessions` (
  `id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `access` int(10) NOT NULL,
  `data` text COLLATE utf8_unicode_ci NOT NULL,
  UNIQUE KEY `id` (`id`)
) ENGINE=InnoDb DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Let’s create a class to manage the sessions, this should include:

  1. Open

  2. Read

  3. Write

  4. Close

  5. Garbage Collection

Let’s create the following class: yourfile.class.php

class WpSessionHandler implements SessionHandlerInterface {

    private $db;
    public function open($savepath, $session_name){
        $user = "user"; 
        $password = "password"; 
        $dbname = "wp_sessions"; 
        $host = "localhost";
        try {
            $this->db = new PDO('mysql:host=' . $host
                . ';dbname=' . $dbname,
                $user, $password);
            return true;
        } catch (Exception $e) {
            return false;
        }
    }

    public function read($id)
    {
        $query = $this->db->prepare("SELECT data FROM sessions WHERE id = ?;");
        $query->execute([$id]);
        $row = $query->fetch(PDO::FETCH_OBJ);

        if ($row === false) {
            return ""; 
        } else {
            return $row->data;
        }
    }


    public function write($id, $data)
    {
        $access = time(); //timestamp

        $query = $this->db->prepare("REPLACE INTO sessions (id, access, data) VALUES (?, ?, ?);");
        return $query->execute([$id, $access, $data]);
    }


    public function destroy($id)
    {
        $query = $this->db->prepare("DELETE FROM sessions WHERE id = ?;");
        return $query->execute([$id]);
    }

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

    public function gc($lifetime)
    {
        $expiration = time() - $lifetime; // actual - lifetime

        $query = $this->db->prepare("DELETE FROM sessions WHERE access < ?;");
        return $query->execute([$expiration]);
    }


}

Now, we need to add the following to the plugin where We are going to use it

require 'sessionhandler.class.php';


$NewSesHandler = new WpSessionHandler();
session_set_save_handler($NewSesHandler);

session_name('my_session_name'); // This will change the cookie name 

Now, just try going to the livechat and ask wpengine to add the cookie name you are using in their caching system and you should be good.

As I said above this works for me and my needs if you need to do something more complex I will save you some time, look at the following references since those are the only ones you might find.

REFERENCES:

https://culttt.com/2013/02/04/how-to-save-php-sessions-to-a-database/

https://brennydoogles.wordpress.com/2011/09/06/taking-control-of-your-php-sessions-using-database-sessions/

https://stackoverflow.com/questions/36753513/how-do-i-save-php-session-data-to-a-database-instead-of-in-the-file-system

https://wordpress.stackexchange.com/questions/123826/session-alternative-for-plugins-due-to-caching

https://www.php.net/manual/en/book.session.php

comments powered by Disqus