2016-06-18 1 views
1

Après la mise à jour vers PHP7, j'ai quelques problèmes avec la gestion des sessions de mes applications.custom session_handler rompu avec php7 (session_set_save_handler)

Il ne semble pas être un gros problème, mais PHP jette cette erreur chaque fois:

[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 

Le session_handler est rien de spécial. Elle stocke les données de session JSONifiées en redis, etc.

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(); 

Toute aide est la bienvenue.

Répondre

1

J'ai le même problème lors de la mise à jour vers PHP7.

Vous obtenez cet avertissement car session_decode() a besoin d'une session active, il remplira $ _SESSION. Ce n'est pas nécessaire, vous voulez seulement désérialiser les données à stocker dans Redis.

C'est la meilleure solution que j'ai trouvée. Vous pouvez utiliser ce class pour désérialiser la session.

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

Votre write() sera:

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. (Mieux vaut tard que jamais) – user2429266

0

Je ne sais pas si cela devrait être considéré comme une réponse correcte, mais c'est une solution qui semble fonctionner.

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

Avec cette option, nous ne avons pas besoin session_decode et peut le remplacer par unserialze() dans la méthode d'écriture.

public function write($id, $data) { 

    $data = unserialize($data); 

    /** do something **/ 

} 

Pour moi, cela ressemble à une solution de contournement.