Nicht immer ist das Problem offensichtlich und dazu gehört eine Fehlerausgabe im Bezug auf die Funktion unserialize(). In diesem Umfeld kommt es auf Grund unsauberer Daten im übergebenen Wert ab und an zu Problemen. Schaut man sich im Netz dazu um, findet man unzählige Hilfesuche und wenige Antworten, da meist das Problem in Quelle liegt, im Wert der übergeben wird. Aber nicht immer hat man darauf Einfluss, insbesondere bei Debugginghelfern kommen da unterschiedliche Inhalte.
Um einigen Hilfesuchenden zu helfen, hier einige Lösungsvorschläge, die man abarbeiten kann. Einige sind nur im Zusammenhang mit WordPress zu nutzen, da die Funktion aus dem Core kommt. Ähnliche Sachen gibt es natürlich auch ohne WP.
Die Erste Lösung ist direkt in den Kommentaren von PHP.net zur Funktion hinterlegt.
$object = preg_replace( '!s:(\d+):"(.*?)";!e', "'s:'.strlen('$2').':\"$2\";'", $object );
Ähnlich geht der folgende Ansatz:
$object = preg_replace( '/;n;/', ';N;', $object );
Alternativ schwören andere auf die Verwendung von trim()
$object = trim( $object );
Aber auch mit diesen Lösungen kommt man nicht immer ans Ziel und die Abfrage, ob es sich um serialisierte Daten handelt muss her. Normalerweise kümmert sich unserialize() darum, aber wie gesagt; nicht immer hilft dies. WordPress stellt eigene Funktionen dafür zur Verfügung.
is_serialized( $data )
is_serialized_string( $data )
Mit diesen beiden Funktion kann sauber abgefragt werden.
Aber auch da kann man mit einem einfachen Snippet ran; eventuell nicht der Weisheit letzter Schluss, daher lieber die Funktionen nutzen oder außerhalb von WP eine eigene Funktion, siehe Gist 1415653.
$is_serialized = preg_match( "/^(O:|a:)/", $object );
Vielleicht hilft es dem einen oder anderen, ansonsten nutze ich es als Gedächtnisstütze.
Einfache Fehlerunterdrückung hilft: https://gist.github.com/1427236
unserialize()bricht ja nicht den Programmfluss ab, von daher verstehe ich nicht wieso man über so was stolpern kann. Entweder die Daten sind deserialisierbar oder nicht. Die allereinfachste Methode ist also$is_serialized = (bool) @unserialize( $object );@Ralf: hilft aber leider nicht in allen Fällen, man stößt massiv auf php Notices; die sind nicht weiter problematisch im live-betrieb, da das @ und die error-settings es unterdrücken. Die obige Lösung war mein erster Ansatz.
Das Problem bei den oben genannten Lösungsansätzen ist, dass die jeweiligen Programmierer festlegen was deserialisierbar ist und was nicht. Ich denke mal das nur PHP entscheiden kann und soll was deserialisierbar ist und was nicht.
Nehmen wir mal an in PHP5.4 würden Daten in einem ganz anderen Format serialisiert. Entweder man würde zwei verschiedene Versionen programmieren oder man würde mit viel Aufwand die Version ermitteln und dann seinen Code anpassen.
Der zweite Nachteil ist, man macht mehr Arbeit. Es wird aufwendig geprüft ob es deserialisierbar ist und hat dann immer noch kein Ergebnis. Man muss dann in einen zweiten Schritt deserialisieren.
Mit der Abfrage
if( $unserialized = @unserialize( $object ) )erledigst du Prüfung und deserialisierung in einen Schritt.Das mit den Notices, da gebe ich dir Recht. Beim Debuggen kann das recht lästig sein. Aber nach einem Durchlauf kennt man seine Pappenheimer und kann die entsprechenden Code-Zeilen bzw. Notices raus filtern.
Ihr habt das Problem meiner Meinung nach völlig richtig erkannt. Ich denke auch, wie Ralf schon oben beschrieben hat, dass die einzelnen Programmierer selbst festlegen was deserialisierbar ist und was eben nicht. Das ich mit der Abfrage if die Prüfung und deserialisierung auf einmal erledigen kann, hab ich jetzt auch gelernt, hab ich davor noch nicht gewusst.