2009-02-10 5 views
10

Ich mag eine session_encode() ‚d Reihe von Sitzungsdaten zu meinem eigenen Array unserialize (das heißt nicht zu $_SESSION.)Wie kann ich Sitzungsdaten zu einer beliebigen Variablen in PHP aus dem Serialisieren entfernen?

Es scheint nicht eine eingebaute Funktion, die diese Griffe. Es gibt session_decode(), aber es schreibt direkt in die $_SESSION super-global. Es gibt unserialize() aber es gibt false auf session_encode() 'd Strings, da sie ein etwas anderes Format sind.

Was ist der beste Weg, dies zu tun?

EDIT: Dies ist der Code, den ich mit gegangen: http://us.php.net/manual/en/function.session-decode.php#79244

Antwort

7

Schauen Sie sich die Kommentare in der session_decode Seite PHP-Handbuch. Es hat eine Reihe von Benutzerfunktionen, um die session_encode Zeichenkette manuell zu entschlüsseln. Soweit ich weiß, ist das der einzige Weg zu gehen.

+0

Ich habe die erste Antwort auf dieser Handbuchseite verwendet. Ich habe meinen Beitrag bearbeitet, um einen direkten Link zu dieser Antwort hinzuzufügen. –

+0

Mir ist aufgefallen, dass die geposteten Lösungen php.net einen gravierenden Makel haben. Ich habe meine eigene Lösung beigesteuert, die die Verwendung eines regulären Ausdrucks vermeidet. Ich werde es auch hier posten. – Halcyon

-7

Warum machst du nicht einfach so etwas?

$myVariable = serialize($_SESSION); 
$sessionCopy = unserialize($myVariable); 

Viel Glück!

+4

Weil Sitzungen in einem anderen Format serialisiert werden als serialisieren/unserialisieren() –

+0

Nun, ja, aber Sie können den session.serialize_handler auf php_serialize setzen. Siehe http://php.net/manual/session.configuration.php#ini.session.serialize-handler für Details – Greg

17

Ich bemerkte, dass die geposteten Lösungen (auf php.net) für die manuelle Dekodierung von Sitzungen nicht perfekt sind, also habe ich eine robustere Lösung beigesteuert.

Die preg_match-Lösung kann niemals funktionieren. Es ist nicht schwer, einen Fall zu finden, der die Deserialisierung durchbrechen könnte. Im Fall von jason-joeymail ist brechen auf:

$_SESSION["test"] = ";oops|"; 

Im Folgenden finden Sie meine Lösung zu finden. Es verwendet keinen regulären Ausdruck, sondern die Reversibilität der Serialisierungsoperation und das "Feature", das serialisiert alle weiteren Eingaben ignoriert, wenn es denkt, dass es fertig ist. Es ist keineswegs eine schöne oder besonders schnelle Lösung, aber es ist eine robustere Lösung. Ich habe einen Deserializer für "php" und "php_binary" hinzugefügt. Es sollte trivial sein, einen für "wddx" hinzuzufügen.

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

Verbrauch:

Session::unserialize(session_encode()); 
+0

+1 Code ist ein bisschen hässlich, aber das ist derjenige, der für mich funktionierte, andere Workarounds nicht. – Mahn

+0

Dies ist nützlich für alle, die Sitzungsdaten von der Befehlszeile aus analysieren möchten, da 'session_decode' nur funktioniert, wenn Sie eine Sitzung geöffnet haben. –

+1

Alle Benchmarks im Vergleich zu den folgenden? '$ cur = Sitzungscode(); session_decode ($ coded_data);/* codierte Daten werden in $ _SESSION */session_decode ($ cur) abgelegt;/* current $ _SESSION restored */' –

1

Der Brauch ‚php‘ deserialise Funktion oben kann durch die Vermeidung des ‚Inkrementieren Offset‘ -Ansatz für allmählich zu essen, um die Input-Mappe String aus sauberen werden.

ich nicht überprüft haben, wie es in Bezug auf die Geschwindigkeit vergleicht, aber es ist sicherlich aufgeräumter (und spart wiederholte Anrufe in der while-Schleife strlen)

$r = array(); 
while ($i = strpos($str, '|')) 
{ 
    $k = substr($str, 0, $i); 
    $v = unserialize(substr($str, 1 + $i)); 
    $str = substr($str, 1 + $i + strlen(serialize($v))); 
    $r[$k] = $v; 
} 
return $r; // session data are now in a normal array 
+0

@Michael Szyndel: Meine Antwort bezog sich speziell auf den 'php'-Handler oben, weil das ein bestimmter Wert in einer" case "-Anweisung war. Durch unnötiges Editieren meines Posts zum Starten von" PHP deserialise .. "Dieses Detail ist verloren gegangen. – itl

0

Das ist für mich gearbeitet:

/* storre current session */ 
$current_session = session_encode(); 

/* extract $other_user_session from file or database, 
    into the $_SESSION global variable */ 
session_decode($other_user_session); 

/* use the other user session data: $something = $_SESSION['something']; */ 

/* restore previous sesison info */ 
session_decode($current_session); /* current $_SESSION restored */ 
0
function data_session_decode($data){ 
    $data = array_filter(explode(';',$data)); 
    $list_data = array(); 
    foreach($data as $key => $dat){ 
     if(!empty($dat)){ 
      $data[$key] = array_filter(explode('|',$dat)); 
      if(substr($data[$key][1], 0, 1) == 'i'){ 
       $list_data[$data[$key][0]] = strstr($data[$key][1], ':'); 
       $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 1); 
      }elseif(substr($data[$key][1], 0, 1) == 's'){ 
       $list_data[$data[$key][0]] = strstr($data[$key][1], '"'); 
       $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 0, -1); 
       $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 1); 
      }else{ 
       unset($data[$key]); 
      } 
     } 
    } 
    unset($data); 
    return $list_data; 
} 

// HIER DATA SESSION EX:

$ Data = 'user_name | s: 8: "You Name"; Datum | i: 1459396063';

// Out

print_r ($ this-> data_session_decode ($ Data));