verschachtelte Serialisierung

14/07/2015 - 10:36 von Stefan+Usenet | Report spam
Beim Versuch, mein Problem mit dem Autoloader zu debuggen, ist mir eine
andere Ungereimtheit aufgefallen - und da die im Gegensatz zum anderen
Problem sehr einfach isolierbar ist, gehe ich sie einmal bevorzugt an.

Die Frage reduziert sich im wesentlichen auf: implementiere ich das
Interface "Serializable" richtig? Falls ja, dann gibt es da IMHO einen
ziemlich unangenehmen Bug - falls nein, wie mache ich es korrekt?

#v+
<?php

class Foo implements Serializable {
private $baz = NULL;

public function __construct(Baz $baz) {
$this->baz = $baz;
}

public function serialize() {
return serialize(array(
'baz' => $this->baz
));
}
public function unserialize($serialized) {
$data = unserialize($serialized);
$this->baz = $data['baz'];
}
}

class Bar extends Foo {
private $bar1 = 'bar';

public function serialize() {
return serialize(array(
'bar1' => $this->bar1,
'parentData' => parent::serialize()
));
}

public function unserialize($serialized) {
$data = unserialize($serialized);
$this->bar1 = $data['bar1'];
parent::unserialize($data['parentData']);
}
}

class Baz implements Serializable {
private $baz1 = 'baz';

public function serialize() {
return serialize(array(
'baz1' => $this->baz1
));
}
public function unserialize($serialized) {
$data = unserialize($serialized);
$this->baz1 = $data['baz1'];
}
}

$baz = new Baz();
$bar1 = new Bar($baz);
$bar2 = new Bar($baz);

$a = [$bar1, $bar2];
var_dump($a);
echo "";
var_dump(unserialize(serialize($a)));

?>
#v-

Das Problem ist schnell beschrieben: unserialize() macht serialize()
nicht korrekt rückgàngig.

Sieht man sich das (im Beispiel nicht ausgegebene) Zwischenergebnis an,
findet man für den Inhalt des zweiten Array-Elements den String:

| C:3:"Bar":73:{a:2:{s:4:"bar1";s:3:"bar";s:10:"parentData";s:20:"a:1:{s:3:"baz";r:4;}";}}}

Interessant ist darin vor allem das 's:3:"baz";r:4;' ganz innen, mit dem
Foo::baz beschrieben wird, und zwar als Referenz auf das bereits zuvor
serialisierte Baz() - wie die "4" genau ermittelt wird, habe ich ad hoc
nicht herausgefunden.

Beim Deserialisieren wird aber (sobald man hierarchisch angeordnete Klassen
verwendet!) ein ganz anderer Wert verwendet, in diesem Fall der String
"bar". Es kann nun die "4" beim Erzeugen der Serialisierung falsch sein,
oder die Auflösung beim Deserialisieren - oder natürlich ich irgendwo einen
Fehler eingebaut haben.

| PHP 5.4.41-1~dotdeb+7.1 (cli) (built: May 15 2015 10:59:59)
| Copyright (c) 1997-2014 The PHP Group
| Zend Engine v2.4.0, Copyright (c) 1998-2014 Zend Technologies
| with Xdebug v2.3.2, Copyright (c) 2002-2015, by Derick Rethans

Servus,
Stefan

http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich
Offizieller Erstbesucher(TM) von mmeike

Stefan, so affig wie die See. Alptràume werden wahr!
(Sloganizer)
 

Lesen sie die antworten

#1 Christoph M. Becker
14/07/2015 - 11:41 | Warnen spam
Stefan Froehlich schrieb:

Beim Versuch, mein Problem mit dem Autoloader zu debuggen, ist mir eine
andere Ungereimtheit aufgefallen - und da die im Gegensatz zum anderen
Problem sehr einfach isolierbar ist, gehe ich sie einmal bevorzugt an.

Die Frage reduziert sich im wesentlichen auf: implementiere ich das
Interface "Serializable" richtig? Falls ja, dann gibt es da IMHO einen
ziemlich unangenehmen Bug - falls nein, wie mache ich es korrekt?



Ich denke, dass Du Serializable "richtig" implementierst, aber über
einen Bug in PHP stolperst: <https://bugs.php.net/bug.php?idi072>. :(

Christoph M. Becker

Ähnliche fragen