更新到PHP7后,我的应用程序会话处理出现了一些问题。
这似乎不是一个大问题,但PHP每次都会抛出此错误:
[18-Jun-2016 20:49:10 UTC] PHP Warning: session_decode(): Session is not active. You cannot decode session data in /var/www/app/phpsessionredis.php on line 90
session_handler没什么特别的。它将JSONified sessiondata存储到redis等。
class phpsessionredis implements \SessionHandlerInterface {
public function __construct( &$redis ) {
$this->__rc = $redis;
}
public function open($savePath, $sessionName) {
return true;
}
public function destroy($id) {
try { $this->__rc->del($id); }
catch (\RedisException $e) { return false; }
}
public function close() {
return true;
}
public function write($id, $data) {
session_decode($data); // throws an error
try{
$this->__rc->setex( $id, 3600, json_encode($_SESSION) );
} catch (\RedisException $e) { return false; }
return true;
}
public function read($id) {
try {
$r = $this->__rc
->multi()
->get($id)
->expire($id, 3600)
->exec();
} catch (\RedisException $e) { return false; }
$_SESSION = json_decode( $r[0], true );
if( isset( $_SESSION ) && ! empty( $_SESSION ) && $_SESSION != null ){
return session_encode();
}
return '';
}
public function gc($maxLifetime) {
return true;
}
}
$sessionhandler = new phpsessionredis( $redis );
session_set_save_handler($sessionhandler);
ob_start();
session_start();
欢迎任何帮助。
答案 0 :(得分:2)
我在更新到PHP7时遇到了同样的问题。
您收到该警告是因为session_decode()
需要一个活动会话,它将填充$ _SESSION。
这不是必需的,您只想反序列化要存储到Redis中的数据。
这是我发现的最佳解决方案。 您可以使用此class来反序列化会话。
<?php
class Session {
public static function unserialize($session_data) {
$method = ini_get("session.serialize_handler");
switch ($method) {
case "php":
return self::unserialize_php($session_data);
break;
case "php_binary":
return self::unserialize_phpbinary($session_data);
break;
default:
throw new Exception("Unsupported session.serialize_handler: " . $method . ". Supported: php, php_binary");
}
}
private static function unserialize_php($session_data) {
$return_data = array();
$offset = 0;
while ($offset < strlen($session_data)) {
if (!strstr(substr($session_data, $offset), "|")) {
throw new Exception("invalid data, remaining: " . substr($session_data, $offset));
}
$pos = strpos($session_data, "|", $offset);
$num = $pos - $offset;
$varname = substr($session_data, $offset, $num);
$offset += $num + 1;
$data = unserialize(substr($session_data, $offset));
$return_data[$varname] = $data;
$offset += strlen(serialize($data));
}
return $return_data;
}
private static function unserialize_phpbinary($session_data) {
$return_data = array();
$offset = 0;
while ($offset < strlen($session_data)) {
$num = ord($session_data[$offset]);
$offset += 1;
$varname = substr($session_data, $offset, $num);
$offset += $num;
$data = unserialize(substr($session_data, $offset));
$return_data[$varname] = $data;
$offset += strlen(serialize($data));
}
return $return_data;
}
}
?>
您的write()
将是:
public function write($id, $data) {
$session_data = Session::unserialize($data);
try{
$this->__rc->setex( $id, 3600, json_encode($session_data) );
} catch (\RedisException $e) { return false; }
return true;
}
答案 1 :(得分:0)
我不知道这是否应该作为正确的答案处理,但它似乎是一种解决方案。
ini_set('session.serialize_handler', 'php_serialize');
使用此选项,我们不需要session_decode,可以在write方法中用unserialze()替换它。
public function write($id, $data) {
$data = unserialize($data);
/** do something **/
}
对我而言,这看起来像是一种解决方法。