Ist es möglich, eine Ausnahme in PHP abzufangen, wenn unserialize()
erzeugt einen Fehler?
Wie kann man eine Deserialisierungsausnahme abfangen?
Eugen
Ein einfacher Weg ist:
$ret = @unserialize($foo);
if($ret === null){
//Error case
}
Aber es ist nicht die modernste Lösung.
Der beste Weg ist, wie bereits erwähnt, ein benutzerdefinierter Fehler-/Ausnahmehandler (nicht nur für diesen Fall). Aber je nachdem, was Sie tun, kann es übertrieben sein.
-
pro Dokumentation: Falls der übergebene String nicht deserialisierbar ist, wird FALSE zurückgegeben. Zum Glück würden nur wenige ausreichen
serialize(false)
– ggesichtslos
29. Januar 2014 um 11:26 Uhr
-
“Falls der übergebene String nicht deserialisierbar ist, wird FALSE zurückgegeben und E_NOTICE wird ausgegeben.” Ein E_ wird ebenfalls geworfen.
– Zedee
29. Mai 2015 um 12:02 Uhr
-
Das
@
Symbol wird für diese Lösung benötigt, da PHP sonst auf dem Bildschirm einen Hinweis ausgibt, wenn die Deserialisierung fehlschlägt.– Flori
19. März 2018 um 9:30 Uhr
-
Das ist keine gute Antwort. Der ursprünglich serialisierte Wert war möglicherweise null.
serialize(NULL)
ist"N;"
was deserialisiert zuNULL
. Niemand serialisiert null unter den meisten Bedingungen, aber dies könnte in einigen komplexen, automatisierten Systemen oder Berechnungen passieren – zB die Ausgabe einer anhaltenden Problemberechnung (wobei NULL nicht dasselbe wie FALSE ist).– S. Kobold
13. September 2018 um 23:13 Uhr
-
Sie müssen die Prüfung auf mindestens ändern
if($foo!="N;" && $ret === null){ //Error case }
Sie wissen also, dass die Quellvariable nicht null war, also wurde null als Fehler zurückgegeben.– Mike
22. Juni 2020 um 0:18 Uhr
Mihai Iorga
Nein, du kannst es nicht fangen, unserialize()
löst keine Exception aus.
Falls der übergebene String nicht deserialisierbar ist, wird FALSE zurückgegeben und E_NOTICE ausgegeben.
Sie können einen benutzerdefinierten Ausnahmehandler festlegen, um alle Fehler zu behandeln:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");
Konvertieren Sie alle PHP-Fehler (Warnhinweise usw.) in Ausnahmen. Beispiel ist hier.
Eine vollständige Lösung würde wie folgt aussehen:
<?php
// As mentioned in the top answer, we need to set up
// some general error handling
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");
// Note, there are two types of way it could fail,
// the fail2 fail is when try to unserialise just
// false, it should fail. Also note, what you
// do when something fails is up to your app.
// So replace var_dump("fail...") with your
// own app logic for error handling
function unserializeSensible($value) {
$caught = false;
try {
$unserialised = unserialize($value);
} catch(ErrorException $e) {
var_dump("fail");
$caught = true;
}
// PHP doesn't have a try .. else block like Python
if(!$caught) {
if($unserialised === false && $value !== serialize(false)) {
var_dump("fail2");
} else {
var_dump("pass");
return $unserialised;
}
}
}
unserializeSensible('b:0;'); // Should pass
unserializeSensible('b:1;'); // Should pass
unserializeSensible('a:2:{s:1:"a";b:0;s:1:"b";s:3:"foo";}'); // Should pass
unserializeSensible('a:2:{s:1:"a";b:0;s:1:"b";s:3:1111111111111111;}'); // Should fail
unserializeSensible(123); // Should fail
unserializeSensible("Gday"); // Should fail
unserializeSensible(false); // Should fail2
unserializeSensible(true); // Should fail
Wie Mihai Iorga erklärte, unserialize
wirft nichts. Sie können nach Fehlern suchen, indem Sie den Rückgabewert mit vergleichen false
aber es schlägt fehl, wenn der serialisierte Wert a ist false
boolescher Wert. Die folgende Lösung löst dieses Problem, ohne auf langsame und umständliche Techniken zurückzugreifen (z. B. das Festlegen benutzerdefinierter Fehlerhandler).
Der folgende Code wirft a InvalidArgumentException
wenn der serialisierte Wert $v
ist ungültig, andernfalls $x
enthält den deserialisierten Wert.
Auf die Unterscheidung wird besonders geachtet:
unserialize()
Rückkehrfalse
um einen ungültigen serialisierten Wert zu signalisieren- der ursprüngliche Wert ist tatsächlich ein boolescher Wert
false
.
$x = @unserialize ($v);
if ($x === false && $v != 'b:0;')
throw new InvalidArgumentException;
-
Jeder kennt die
@
Charakter, aber manchmal vergessen wir die kleinen Kenntnisse.@
Charakter verhindert die Benachrichtigung,-b:0;
ist der serialisierte Wert vonfalse
. Ihre Antwort ist wie ein Blitz in meinem Gehirn eingeschlagen 🙂– kodmanyagha
12. Mai um 19:27 Uhr
Maxim Rysevets
Sie können diese einfache Funktion aus meinem CMS EFFCORE verwenden:
function data_is_serialized($data) {
if ($data === 'b:0;') return true;
if (is_string($data) && @unserialize($data, ['allowed_classes' => ['stdClass']]) !== false) return true;
return false;
}
Prüfen:
var_dump( data_is_serialized(0) === false );
var_dump( data_is_serialized(1) === false );
var_dump( data_is_serialized('') === false );
var_dump( data_is_serialized('0') === false );
var_dump( data_is_serialized('1') === false );
var_dump( data_is_serialized(true) === false );
var_dump( data_is_serialized(false) === false );
var_dump( data_is_serialized([]) === false );
var_dump( data_is_serialized(serialize(0)) === true );
var_dump( data_is_serialized(serialize(1)) === true );
var_dump( data_is_serialized(serialize('')) === true );
var_dump( data_is_serialized(serialize('0')) === true );
var_dump( data_is_serialized(serialize('1')) === true );
var_dump( data_is_serialized(serialize(true)) === true );
var_dump( data_is_serialized(serialize(false)) === true );
var_dump( data_is_serialized(serialize([])) === true );
-
Jeder kennt die
@
Charakter, aber manchmal vergessen wir die kleinen Kenntnisse.@
Charakter verhindert die Benachrichtigung,-b:0;
ist der serialisierte Wert vonfalse
. Ihre Antwort ist wie ein Blitz in meinem Gehirn eingeschlagen 🙂– kodmanyagha
12. Mai um 19:27 Uhr
RedDragonWebDesign
In meinem Fall gab unserialize leer zurück, wenn es fehlschlug, nicht null.
$ret = @unserialize($foo);
if ( ! $ret ) {
//Error case
}