I've just migrated from PHP 7.0 to PHP 7.1 (fresh/clean install of the current version of WAMP) on a computer and it seems to have broken something in the custom session handler that's supposed to save the session to the database instead of using the file system.
The custom hander class is:
class db_session_handler implements SessionHandlerInterface {
public function __construct($db) {
$this->db = $db;
}
public function open($save_path,$session_name) {
$this->db;
return true;
}
public function close() {
unset($this->db);
return true;
}
public function read($session_id) {
if (!isset($session_id)) {
$session_id='';
}
try {
$sql="
SELECT
sess_data
FROM
ue_user_session
WHERE
sess_id = :sess_id
";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':sess_id', $session_id);
$stmt->execute();
$res = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (count($res) <> 1 ) {
return false;
} else {
return $res[0]['sess_data'];
}
}
catch (PDOException $e) {
error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
return false;
}
}
public function write($session_id,$session_data) {
try {
$sql="
SELECT
sess_data
FROM
ue_user_session
WHERE
sess_id = :sess_id
";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':sess_id', $session_id);
$stmt->execute();
$res = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
catch (PDOException $e) {
error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
return false;
}
$ip = get_ip();
if (isset($_SESSION['user_id'])) {
$user_id = (int) $_SESSION['user_id'];
} else {
$user_id= (int) 0;
}
if (empty($res)) {
if (!isset($_SERVER['REDIRECT_URL'])) {
$location = 'Unknown';
} else {
$location = $_SERVER['REDIRECT_URL'];
}
try {
if (count($res) === 0) {
$sql="
INSERT INTO
ue_user_session
(
sess_id
, user
, start
, last_activity
, location
, ip
, user_agent
, user_host
, user_language
, expires
, sess_data
)
VALUES
(
:sess_id
, 0
, NOW()
, NOW()
, :location
, :ip
, :user_agent
, :user_host
, :user_lang
, DATE_ADD(NOW(), INTERVAL 30 MINUTE)
, :sess_data
)
";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':sess_id', $session_id);
$stmt->bindParam(':location', $location);
$stmt->bindParam(':ip', $ip);
$stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);
$stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);
$stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$stmt->bindParam(':sess_data', $session_data);
$stmt->execute();
return true;
}
}
catch (PDOException $e) {
error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
return false;
}
} else {
try {
$sql="
UPDATE
ue_user
SET
last_activity = NOW()
WHERE
id = :user_id
";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':user_id', $user_id);
$stmt->execute();
}
catch (PDOException $e) {
error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
return false;
}
if (!isset($_SERVER['REDIRECT_URL'])) {
$location = 'Unknown';
} else {
$location = $_SERVER['REDIRECT_URL'];
}
try {
$sql="
UPDATE
ue_user_session
SET
last_activity = NOW()
, expires = DATE_ADD(NOW(), INTERVAL 30 MINUTE)
, location = :location
, ip = :ip
, user_agent = :user_agent
, user_host = :user_host
, user_language = :user_lang
, sess_data = :sess_data
, user = :user_id
WHERE
sess_id = :sess_id
";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':location', $location);
$stmt->bindParam(':ip', $ip);
$stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);
$stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);
$stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$stmt->bindParam(':sess_data', $session_data);
$stmt->bindParam(':user_id', $user_id);
$stmt->bindParam(':sess_id', $session_id);
$stmt->execute();
return true;
}
catch (PDOException $e) {
error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
return false;
}
}
$this->gc();
}
public function destroy($session_id) {
try {
$sql="
DELETE FROM
ue_user_session
WHERE
sess_id = :sess_id
";
$stmt = $this->db->prepare($sql);
$stmt->bindParam(':sess_id', $session_id);
$stmt->execute();
return true;
}
catch (PDOException $e) {
error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
return false;
}
}
public function gc($max_lifetime) {
try {
$sql="
DELETE FROM
ue_user_session
WHERE
NOW() > expires
";
$stmt = $this->db->prepare($sql);
$stmt->execute();
return true;
}
catch (PDOException $e) {
error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
return false;
}
}
}
It's initilised by:
ini_set('session.use_only_cookies', 1);
$db_session_handler = new db_session_handler($db);
session_set_save_handler($db_session_handler, true);
if (session_start() === false ) {
die('The Session Handler Is Broken!!!!');
}
Reading through the manual page for session_set_save_handler() I can't spot anything mentioned that might explain the error that I'm getting which is:
Warning: session_start(): Failed to read session data: user (path: c:/wamp/tmp) in C:\wamp\www\universal_empires\libs\bootstrap.php on line 36
Line 36 in that file is the call to session_start().
Googling around the only fixes that I can find are specific to a given framework. What I need to know is what's causing session_start() to fail (from reading about changes to 7.1 session_start() returns false instead of trying to plod on when something's not right.
My guess is that something has changed in 7.1 where in 7.0 possibly it was allowed to carry on but in 7.1 it's more stricter with whatever the problem is and makes session_start() return false.
I've emptied the sessions table in the database and have checked where file-based sessions get stored. The only "file-based" session file present is PHPMyAdmin.
Does anyone know what it's falling foul of in PHP 7.1 that it doesn't fall foul of in PHP 7.0?