问题
The development environment of my application is Zend Framework 1.11, MSSQL Server 2012, SQLSRV Extension for Database connectivity with PDO, Windows 7, IIS 7. Session is being stored in database by using custom session handler class.
The issue is that when i print $_SESSION after session_start() which is written in Bootstrap.php file, it does not show complete unserialized array of session data. It seems that session data which is being returned by "read" method of session class handler, not being unserialized for some reason. Here is my source code:-
Bootstrap.php
protected function _initSession() {
$handler = new Mcd_Core_SessionHandler_Database();
session_set_save_handler(
array($handler, 'open'),
array($handler, 'close'),
array($handler, 'read'),
array($handler, 'write'),
array($handler, 'destroy'),
array($handler, 'gc')
);
session_start();
echo "<pre>";
print_r($_SESSION);
}
SessionHandler Class
<?php
class My_Core_SessionHandler_Database
{
protected $dbh;
protected $ipAddress = '';
public function __construct() {
$this->dbh = My_Core_Config::get_dbinstance();
}
public function open($savePath, $sessionId) {
return true;
}
public function close() {
return true;
}
public function read($sessionId) {
$query = "SELECT TOP 1 CAST(session as varchar(max)) as session
FROM t_php_session
WHERE php_session_id = '".$sessionId."'
AND DATEADD(minute, ".My_Core_Config::get_value('session_timeout_period').", created) >= GETDATE()
AND user_ip = '".$this->ipAddress."'";
$stmt = $this->dbh->prepare($query);
$stmt->execute();
$result = $stmt->fetchColumn();
if ($result === false) {
return '';
}
return $result;
}
public function write($sessionId, $sessionData) {
$query = "
SELECT id
FROM t_php_session
WHERE php_session_id = ?
";
$stmt = $this->dbh->prepare($query);
$stmt->execute(array($sessionId));
$result = $stmt->fetchColumn();
if (empty($result)) {
$query = "INSERT INTO t_php_session (php_session_id, session, user_ip, created) VALUES (?, CONVERT(VARBINARY(max), ?), ".$this->ipAddress.", GETDATE())";
$stmt = $this->dbh->prepare($query);
$stmt->execute(array($sessionId, $sessionData));
} else {
$query = "
UPDATE t_php_session
SET session = CONVERT(VARBINARY(max), ?),
user_ip = ".$this->ipAddress.",
created = GETDATE()
WHERE id = ?
";
$stmt = $this->dbh->prepare($query);
$stmt->execute(array($sessionData, $result));
}
return true;
}
public function destroy($sessionId) {
$query = 'DELETE FROM t_php_session WHERE php_session_id = ?';
$stmt = $this->dbh->prepare($query);
$stmt->execute(array($sessionId));
return true;
}
public function gc($maxlifetime) {
$query = "
DELETE FROM t_php_session
WHERE DATEADD(minute, ".My_Core_Config::get_value('session_timeout_period').", created) < GETDATE()";
$stmt = $this->dbh->prepare($query);
$stmt->execute();
return true;
}
}
The datatype of session field in the database table is varbinary (max). I just guess this might be the issue but not sure.
Output of read method of session handler class is:
My_Core_Session|a:1:{s:16:"My_Core_Session";a:4:{s:19:"previous_controller";N;s:15:"previous_action";N;s:18:"current_controller";s:16:"authentification";s:14:"current_action";s:5:"login";}}
Output of $_SESSION in Bootstrap.php is:
Array
(
[My_Core_Session] =>
)
Where as the output should be:
Array
(
[My_Core_Session] => Array
(
[My_Core_Session] => Array
(
[previous_controller] =>
[previous_action] =>
[current_controller] => authentification
[current_action] => login
)
)
)
This application is working fine on Linux as same database, source code is being used but with different environment like Apache 2.2, FreeTDS, Dblib. We just moved this application from Linux to Windows and facing this issue.
回答1:
I found the solution and would like to share it with those people who may face the same problem. The issue was that PHP engine was not able to deserialize the session data that was being fetched from MSSQL Server database may be some garbage was coming along with the data. The data type of the field (where session was being saved) was varbinary (max). I simply changed it to varchar (max) to see if it works and it worked :)
This is a specific use case where custom session handler was used in zend framework with MSSQL Server database. Luckily, it is resolved now :)
Good Luck !!
来源:https://stackoverflow.com/questions/31050463/php-custom-session-handler-unserialize-not-working-on-windows