PDO kann man nicht serialisieren? Oh doch!

Gerade habe ich einen Bug behoben, der mich am Anfang doch sehr durcheinander gebracht hat. Die Lösung dieses Bugs möchte ich Euch hier nicht vorenthalten.

Der Bug

Im aktuellen Woltlab Comunity Framework (WCF) gibt es ein wunderschönes Cache Objekt, welches Daten unter anderem auch als Cache Datei auf den Server schreibt. Innerhalb eines dieser Cache Objekte habe ich ein neues Datenobjekt erzeugt. Bei der Erzeugung des Datenobjekts wurde ein PDO Objekt übergeben. Genau hier erfolgte auch der Fehler. Eine PDOException sagte, dass die PDO Instanz nicht serialisiert werden kann:

You cannot serialize or unserialize PDO instances

Sichrlich hat PHP sehr gute Gründe für dieses Verhalten. Für mich war es in dieser Situation erstmal komplett neu. Hier noch ein kleines Beispiel, so dass auch wirklich klar wird, wie der Fehler entsteht.

try {
    $dbHandle = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'username', 'password');
    
    function letsCrash($dbh) {
        echo serialize($dbh);
    }
    letsCrash($dbHandle);
} catch (PDOException $e) {
    echo $e->getMessage();
}

Die Lösung

Die Lösung liegt wie so oft bei einem der vielen Interfaces, die PHP von Hause aus mitliefert. Das Serializable Interface ermöglicht das Serialisieren von Objekten auch mit einem PDO Member, indem es die herkömmlichen PHP Funktionen serialize() und unserialize() überschreibt. Anhand eines WCF Datenobjekts lässt sich das sehr schön praktisch zeigen:

class MyData extends DatabaseObject implements Serializable {
    protected $dbHandle = null;
    
    public function __construct(PDO $dbHandle, $dataID) {
        $this->dbHandle = $dbHandle;
        ...
    }

    public function serialize() {
        return serialize($this->data);
    }

    public function unserialize($serializedData) {
        $this->data = unserialize($serializedData);
    }
}

Wie ihr seht, implementiert das Serializable Interface die beiden Methoden serialize() und unserialize(). Innerhalb der serialize() Methode definiere ich nun genau die Daten, die serialisiert werden sollen. Ich schließe hier das PDO Objekt explizit aus. Somit verhindere ich, dass eine PDOException geworfen wird. Und mal ehrlich … wozu brauchen wir ein PDO Objekt im Cache? Braucht kein Mensch. Die unserialize() Methode deserialisiert unsere Daten aus dem Cache wieder ganz normal.

So kann das WCF Cache Objekt auch mit Dependency Injection und nicht serialisierbaren Objekten wie PDO umgehen.

2 Gedanken zu „PDO kann man nicht serialisieren? Oh doch!“

Kommentar verfassen

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.