2016-06-18 38 views
1

更新到PHP7後,我的應用程序會話處理有一些問題。自定義session_handler與php7(session_set_save_handler)斷開

它似乎並沒有成爲一個大問題,但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什麼特別的。它將JSON化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(); 

任何幫助都是值得歡迎的。

回答

1

我在更新到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; 

} 
+0

THX。 ( 遲到總比不到好 ) – user2429266

0

我不知道這應該作爲一個正確的答案來處理,但它似乎工作的解決方案。

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

使用此選項我們不需要session_decode,並且可以在寫入方法內用unserialze()替換它。

public function write($id, $data) { 

    $data = unserialize($data); 

    /** do something **/ 

} 

對我來說這看起來像一個解決方法。