пользовательский обработчик сессии не работает с php7 (session_set_save_handler)

После обновления до 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

Обработчик сессии ничего особенного. Он хранит JSONified данные сеанса в 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();

Любая помощь приветствуется.

2

Решение

У меня та же проблема при обновлении до PHP7.

Вы получаете это предупреждение, потому что session_decode() нужен активный сеанс, он заполнит $ _SESSION.
Это не нужно, вам нужно всего лишь отменить сериализацию данных, которые будут сохранены в Redis.

Это лучшее решение, которое я нашел.
Вы можете использовать это учебный класс десериализовать сессию.

<?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;

}
2

Другие решения

Я не знаю, следует ли считать это правильным ответом, но похоже, что это решение работает.

ini_set('session.serialize_handler', 'php_serialize');

С этой опцией нам не нужен session_decode, и мы можем заменить его на unserialze () в методе write.

public function write($id, $data) {

$data = unserialize($data);

/** do something **/

}

Для меня это выглядит как обходной путь.

0

По вопросам рекламы [email protected]