Link to home
Start Free TrialLog in
Avatar of tonelm54
tonelm54

asked on

PHP Session store in database

I have some code which stores session detail in a database, but when I issue the command 'session_regenerate_id();' I get
PHP Catchable fatal error:  session_regenerate_id(): Failed to create(read) session ID

<?php
    //Session
    class pdoSession {
        //DB Object
        private $db;

        public function __construct($pdoDB){
            // Instantiate new Database object
            $this->db = $pdoDB;

            // Set handler to overide SESSION
            session_set_save_handler(
                array($this, "_open"),
                array($this, "_close"),
                array($this, "_read"),
                array($this, "_write"),
                array($this, "_destroy"),
                array($this, "_gc")
            );

            // Start the session
            session_start();
        }

        //Open
        public function _open(){
            // If successful
            if($this->db){
                return true;
            }
            // Return False
            return false;
        }

        //Close
        public function _close(){
            // Close Session
            return true;
        }

        //Read
        public function _read($id){
            $stSession = $this->db->prepare("SELECT `data` FROM `sessions` WHERE `SID` = :id");
            $stSession->bindValue(':id', $id, PDO::PARAM_STR);

            if($stSession->execute()){
                $row = $stSession->fetch(PDO::FETCH_ASSOC);
                return $row['data'];
            }else{
                return '';
            }
        }

        //Write
        public function _write($id, $data){
			
            $access = time();

            // Set query
            $stWrite = $this->db->prepare("REPLACE INTO `sessions` VALUES (:id, :data, :access);");

            // Bind data
            $stWrite->bindValue(':id', $id, PDO::PARAM_STR);
            $stWrite->bindValue(':access', $access, PDO::PARAM_INT);
            $stWrite->bindValue(':data', $data, PDO::PARAM_LOB);

            // Attempt Execute if successful
            if($stWrite->execute()){
                return true;
            } else {
				echo "\nPDO::errorInfo():\n";
				print_r($stWrite->errorInfo());
				exit();
                return false;
            }
        }

        //Destroy
        public function _destroy($id){
            // Set query
            return true;
            $stDestroy = $this->db->prepare("DELETE FROM `sessions` WHERE `SID` = :id;");

            // Bind data
            $stDestroy->bindValue(':id', $id, PDO::PARAM_STR);

            // Attempt execution if successful
            if($stDestroy->execute()){
                return true;
            } else {
                return false;
            }
        }

        //Garbage Collection
        public function _gc($max){
            // Calculate what is to be deemed old
            $old = time() - $max;

            // Set query
            $stGC = $this->db->prepare('DELETE * FROM `sessions` WHERE `access` < :old');

            // Bind data
            $stGC->bindValue(':old', $old, PDO::PARAM_INT);

            // Attempt execution
            if($stGC->execute()){
                return true;
            } else {
                return false;
            }
        }
    }

    session_set_save_handler(new pdoSession($pdoDB), true);
?>

Open in new window


Ive done a google search and cannot find any fixes around this.

Any ideas how I can fix this?

Thank you
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Why are you using the object method and in the constructor calling session_set_save_handler again using the prodeural signature  with your object methods as parameters.

Why not simply implement the SessionHandlerInterface and have your object methods handle the close / destroy /gc etc?
Avatar of tonelm54
tonelm54

ASKER

OK, so following that I rewote my class to:-
class MySessionHandler implements SessionHandlerInterface
{
	private $pdoConn;

	public function setPDO($pdoConn) {
			$this->pdoConn = $pdoConn;
	}
		
	public function open($save_path, $session_name){
		if (empty($this->pdoConn)) {
			die("Session PDO Not set");
		}
		return true;
	}
    public function close()
    {
        return true;
    }

    public function read($id)
    {
		$stSession = $this->pdoConn->prepare("SELECT `data` FROM `sessions` WHERE `SID` = :id");
		$stSession->bindValue(':id', $id, PDO::PARAM_STR);

		if($stSession->execute()){
			$row = $stSession->fetch(PDO::FETCH_ASSOC);
			return $row['data'];
		}else{
			return '';
		}
    }

    public function write($id, $data)
    {
		$access = time();
		$stWrite = $this->pdoConn->prepare("REPLACE INTO `sessions` VALUES (:id, :data, :access);");
		$stWrite->bindValue(':id', $id, PDO::PARAM_STR);
		$stWrite->bindValue(':access', $access, PDO::PARAM_INT);
		$stWrite->bindValue(':data', $data, PDO::PARAM_LOB);

		if($stWrite->execute()){
			return true;
		} else {
			echo "\nPDO::errorInfo():\n";
			print_r($stWrite->errorInfo());
			exit();
			return false;
		}
    }

    public function destroy($id) {
		$stDestroy = $this->pdoConn->prepare("DELETE FROM `sessions` WHERE `SID` = :id;");

		// Bind data
		$stDestroy->bindValue(':id', $id, PDO::PARAM_STR);

		// Attempt execution if successful
		if($stDestroy->execute()){
			return true;
		} else {
			return false;
		}
    }

    public function gc($maxlifetime) {
		$old = time() - $maxlifetime;

		$stGC = $this->pdoConn->prepare('DELETE * FROM `sessions` WHERE `access` < :old');

		$stGC->bindValue(':old', $old, PDO::PARAM_INT);

		if($stGC->execute()){
			return true;
		} else {
			return false;
		}
    }
}

$handler = new MySessionHandler();
$handler->setPDO($pdoDB);
session_set_save_handler($handler, true);
session_start();

Open in new window


However when I try the
session_regenerate_id()
I get
User generated image
I also tried doing:-
	session_destroy();
	session_start();

Open in new window

Which I hoped would generate a new sessionID but it kept the same ID.

Any suggestions?

Thank you
I also tried:-
session_id("erwgwrg4rg425g45g45g");

Open in new window


However when I refreshed the page and looked at session ID it was the original sessionID instead of the newly set one.

Any suggestions?
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
HUGE Thank you for this :-)
You are welcome.