Database PHP Session Storage & Handling PHP 5.4+

I’ve started recoding a site and have got stuck trying to update my session class to work with PHP version 5.4

    
    public function __construct($db) {
        $this->db = $db;
        session_set_save_handler(
                              array($this, 'open')
                            , array($this, 'close')
                            , array($this, 'read')
                            , array($this, 'write')
                            , array($this, 'destroy')
                            , array($this, 'gc')
                            );
          $this->session_expire_time    = get_cfg_var("session.gc_maxlifetime");
          session_start();
      }
      

That’s the constructor for the old session class, this is the new session class as it stands (basically as is from the PHP Anthology book)

<?php
/**
 *  A session handling class.
 *  A custom session handling class that will save the session 
 *  data to a MySQL database using PDO.  Because of the fixed  
 *  input params to the various functions I sometimes get values  
 *  and do nothing with them.
 * 
 *  Some basic error handling has been implemented with sending 
 *  error messages to the error log.  This can of course be modified 
 *  to work with any error handling logic dictated by the
 *  business rules.
 * 
 *  @param string $sess_table
 *  @param string $sess_db
 *  @param string $sess_db_host
 *  @param string $sess_db_usr
 *  @param string $sess_db_pass
 *  @param mixed $db
 *
 *  @uses PDO
 * 
 *  @todo this has had next to no testing done on it... need to 
 *  write a couple of test scripts for it.
 */
class session implements SessionHandlerInterface
{
  /**
   * table with session data 
   *
   * @var string
   * @access private
   */
  private $sess_table;
  
  /**
   * database where session table is 
   * 
   * @var string
   * @access private 
   */
  private $sess_db;
  
  /**
   * the server where the session database is 
   * 
   * @var string
   * @access private 
   */
  private $sess_db_host;
  
  /**
   * the user to access the session database 
   * 
   * @var string
   * @access private
   */
  private $sess_db_usr;
  
  /**
   * the password to access the session database 
   * 
   * @var string
   * @access private 
   */
  private $sess_db_pass;
  
  /**
   * The database connection object
   * 
   * @param mixed
   * @access private 
   */
  private $db;

     /**
      * Moves the database access information to class vars.
      * 
      * @param string $sess_table
      * @param string $sess_db
      * @param string $sess_db_host
      * @param string $sess_db_usr
      * @param string $sess_db_pass
      * @access public
      * @return void
      */
  public function __construct($db) {
      $this->db = $db;
      $this->sess_table = 'ue_user_session';
      session_set_save_handler(array($this, 'open'),
    array($this, 'close'),
    array($this, 'read'),
    array($this, 'write'),
    array($this, 'destroy'),
    array($this, 'gc')
);
session_start();

  }

     /**
      * Open a session by making a connection to the database holding 
      * the session data.
      * Return true or false.  Writes to the default error log if 
      * there is a problem.
      * 
      * @param $open
      * @param $path
      * @access public
      * @return bool 
      */
  public function open($path, $name)
  {
    return true;
  }

     /**
      * close the database connection and end the session 
      * Return true or false.
      * 
      * @access public
      * @return bool
      */
  public function close()
  {
    $this->db = null;
    return true;
  }

     /**
      * retrieve the session data from the DB and place it in a string.
      * Must return a string - even an empty one.  Writes to the default 
      * error log if there is a problem.
      * 
      * @param mixed $sess_id
      * @access public
      * @return string
      */
  public function read($sess_id)
  {
    try
    {
      $sql = "SELECT sess_data FROM {$this->sess_table} WHERE sess_id = :id";
      $stmt = $this->db->prepare($sql);
      $stmt->execute(array(':id'=>$sess_id));
      $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    catch (PDOException $e)
    { 
      error_log('Error reading the session data table in the session reading method.');
      error_log(' Query with error: '.$sql);
      error_log(' Reason given:'.$e->getMessage()."\
");
      return ''; 
    }
    if (count($res) > 0)
    {   
      return isset($res[0]['sess_data']) ? $res[0]['sess_data'] : '';
    }
    else
    {
      return '';
    }
  }

     /**
      * Insert or update session data in the DB.
      * Return true or false.  Writes to the default error log if 
      * there is a problem.
      * 
      * @param $sess_id
      * @param $data
      * @access public
      * @return bool
      */
  public function write($sess_id, $data)
  {
    try
    {
      $sql = "SELECT sess_data FROM {$this->sess_table} WHERE sess_id = :id";
      $stmt = $this->db->prepare($sql);
      $stmt->execute(array(':id'=>$sess_id));
      $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
    }
    catch (PDOException $e)  
    { 
      error_log('Error reading the session data table in the session writing method.');
      error_log(' Query with error: '.$sql);
      error_log(' Reason given:'.$e->getMessage()."\
");
      return false; 
    }
    try
    {
      if (count($res) > 0) 
      {
        $sql = "UPDATE {$this->sess_table} SET sess_last_acc = NOW(), sess_data = :data" .
            " WHERE sess_id = :id";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':data', $data);
        $stmt->bindParam(':id', $sess_id); 

      }
      else 
      {
        $sql ="INSERT INTO {$this->sess_table}(sess_id," .
            " sess_start, sess_last_acc," .
            " sess_data) VALUES (:id, NOW(), NOW(), :data)";
        $stmt = $this->db->prepare($sql);
        $stmt->bindParam(':id', $sess_id);
        $stmt->bindParam(':data', $data); 
      }
      $res = $stmt->execute();
    }
    catch (PDOException $e)
    {
      error_log('Error writing to the session data table.');
      error_log('Query with error: '.$sql);
      error_log('Reason given:'.$e->getMessage()."\
");
      return false;
    }
    return true;
  }

     /**
      * Delete the session data row in the database
      * Return true or false.  Writes to the default error log 
      * if there is a problem.
      * 
      * @param $sess_id
      * @access public
      * @return bool
      */
  public function destroy($sess_id)
  {
    try
    {
      $sql = "DELETE FROM {$this->sess_table} WHERE sess_id = :id";
      $stmt = $this->db->prepare($sql);
      $stmt->execute(array(':id'=>$sess_id)); 
    }
    catch (PDOException $e)
    {
      error_log('Error destroying the session.');
      error_log('Query with error: '.$sql);
      error_log('Reason given:'.$e->errorMessage()."\
");
      return false;
    }
    return true;
  }

     /** 
      * Garbage collector for those that don't properly end 
      * a session or the session times out. Writes to the 
      * default error log if there is a problem.
      * 
      * @param $ttl
      * @access public
      * @return bool
      */
  public function gc($ttl)
  {
    $end = time() - $ttl;
    try
    {
      $sql = "DELETE FROM {$this->sess_table} WHERE sess_last_acc <:end";
      $stmt = $this->db->prepare($sql);
      $stmt->execute(array(':id'=>$end));
    }
    catch (PDOException $e)
    {
      error_log('Error with the garbage collection method of the session class.');
      error_log('Query with error: '.$sql);
      error_log('Reason given:'.$e->getMessage());
      return false;
    }
    // may want to consider optimizing the table at a given rate to clean up all the 
    // deletes of a high traffic site - maybe use OPTIMIZE
    return true;
  }

  /**
  * class desructor
  * because of a few changes in the implementation of the way
  * sessions are closed out (after PHP v. 5.0.5) - when a page  
  * is done we now have to explicitly call the write and close 
  * ourselves.  PHP no longer does it automagically for us.
  * 
  * @param void
  * @return void
  */
  public function __destruct()
  {
    session_write_close();
  } 
}
?>

The only real difference that I’ve made is the change of the class name,

session implements SessionHandlerInterface

the use of

      $this->db = $db;
      session_set_save_handler(array($this, 'open'),
    array($this, 'close'),
    array($this, 'read'),
    array($this, 'write'),
    array($this, 'destroy'),
    array($this, 'gc')
);
session_start();

in the constructor

And the removal of the estblishment of the database connection in the open method (I try and use a single instance of the database class (now PDO) throughout the app so that i’m not constantly opening and closing database connections everywhere.

No matter what I’ve tried it outright refuses to use the database.

What specific error message do you receive?

Without knowing that it is difficult for us to understand what is happening.

For example this could just as well be that the problem is that the database class is destroyed before the session close is handled, compared to that it does not want to use the database. As this is a common problem when you pass along a instance of the connection to the session handler.

If you dont receive any errors, try adding this right after setting the session handler.

register_shutdown_function(“session_write_close”);