Start · Sprachen · PHP · Referenz · MongoDB\BSON\Persistable

MongoDB\BSON\Persistable

Interface

Interface für PHP-Klassen, die beim Speichern in und Lesen aus MongoDB automatisch mit Typinformation serialisiert und deserialisiert werden.

seit PHP 1.0.0 Kategorie: db

Signatur

interface MongoDB\BSON\Persistable extends MongoDB\BSON\Unserializable, MongoDB\BSON\Serializable

Beschreibung

MongoDB\BSON\Persistable kombiniert die Interfaces MongoDB\BSON\Serializable und MongoDB\BSON\Unserializable. Klassen, die dieses Interface implementieren, werden beim Schreiben in MongoDB automatisch mit einem speziellen Feld __pclass versehen, das den vollqualifizierten PHP-Klassennamen enthält. Beim Lesen der Daten aus der Datenbank wird dieses Feld genutzt, um das Dokument automatisch wieder als Instanz der ursprünglichen Klasse zu deserialisieren.

Durch die Implementierung von bsonSerialize() legt man fest, welche Eigenschaften des Objekts als BSON-Dokument gespeichert werden. Die Methode bsonUnserialize() empfängt beim Lesen ein Array der gespeicherten Felder und befüllt das Objekt damit. Diese Trennung gibt der Anwendung vollständige Kontrolle über den Serialisierungsprozess und erlaubt zum Beispiel das Auslassen interner Felder oder das Transformieren von Werten.

Das Interface eignet sich besonders dann, wenn die Anwendungsdomäne klare Entitätsklassen (z. B. User, Order) besitzt und diese ohne explizites Mapping direkt aus MongoDB gelesen werden sollen. Es ist eine Alternative zu reinen stdClass- oder Array-Ergebnissen und ermöglicht typsicheres Arbeiten mit Datenbankdokumenten.

  • Beim Schreiben: bsonSerialize() muss ein array oder ein Objekt zurückgeben, das in ein BSON-Dokument umgewandelt werden kann.
  • Beim Lesen: bsonUnserialize(array $data) erhält alle gespeicherten Felder (ohne __pclass) und soll damit das Objekt initialisieren.

Beispiele

Einfache Entitätsklasse mit Persistable

<?php
use MongoDB\BSON\Persistable;
use MongoDB\BSON\ObjectId;

class User implements Persistable
{
    private ObjectId $id;
    private string $name;
    private string $email;

    public function __construct(string $name, string $email)
    {
        $this->id    = new ObjectId();
        $this->name  = $name;
        $this->email = $email;
    }

    public function bsonSerialize(): array
    {
        return [
            '_id'   => $this->id,
            'name'  => $this->name,
            'email' => $this->email,
        ];
    }

    public function bsonUnserialize(array $data): void
    {
        $this->id    = $data['_id'];
        $this->name  = $data['name'];
        $this->email = $data['email'];
    }

    public function getName(): string  { return $this->name; }
    public function getEmail(): string { return $this->email; }
}

// Verbindung herstellen
$client     = new MongoDB\Client('mongodb://localhost:27017');
$collection = $client->mydb->users;

// Objekt speichern — __pclass wird automatisch hinzugefügt
$user = new User('Maria Müller', 'maria@example.com');
$collection->insertOne($user);

// Objekt lesen — automatisch als User-Instanz deserialisiert
$result = $collection->findOne(['name' => 'Maria Müller']);
echo get_class($result) . PHP_EOL; // User
echo $result->getName()  . PHP_EOL; // Maria Müller
User Maria Müller

Verschachtelte Persistable-Klassen

<?php
use MongoDB\BSON\Persistable;

class Address implements Persistable
{
    public string $city;
    public string $zip;

    public function __construct(string $city, string $zip)
    {
        $this->city = $city;
        $this->zip  = $zip;
    }

    public function bsonSerialize(): array
    {
        return ['city' => $this->city, 'zip' => $this->zip];
    }

    public function bsonUnserialize(array $data): void
    {
        $this->city = $data['city'];
        $this->zip  = $data['zip'];
    }
}

class Customer implements Persistable
{
    public string  $name;
    public Address $address;

    public function __construct(string $name, Address $address)
    {
        $this->name    = $name;
        $this->address = $address;
    }

    public function bsonSerialize(): array
    {
        return [
            'name'    => $this->name,
            'address' => $this->address, // wird ebenfalls mit __pclass serialisiert
        ];
    }

    public function bsonUnserialize(array $data): void
    {
        $this->name    = $data['name'];
        $this->address = $data['address']; // automatisch als Address deserialisiert
    }
}

$client     = new MongoDB\Client('mongodb://localhost:27017');
$collection = $client->mydb->customers;

$address  = new Address('Berlin', '10115');
$customer = new Customer('Hans Schmidt', $address);
$collection->insertOne($customer);

$found = $collection->findOne(['name' => 'Hans Schmidt']);
echo get_class($found->address) . PHP_EOL; // Address
echo $found->address->city       . PHP_EOL; // Berlin
Address Berlin

// Wichtig · Fallstricke

__pclass-Feld: MongoDB speichert den PHP-Klassennamen automatisch im Feld __pclass als Binary-Typ (Subtype 0x80). Dieses Feld sollte nicht manuell in bsonSerialize() zurückgegeben werden, da es der Treiber selbst hinzufügt. Wird die Klasse umbenannt oder verschoben, können bestehende Dokumente nicht mehr automatisch deserialisiert werden — planen Sie Migrationen entsprechend.

Sicherheit: Da beim Lesen beliebige Klassen aus der Datenbank instanziiert werden können, sollte sichergestellt werden, dass nur vertrauenswürdige Klassenbezeichnungen im __pclass-Feld gespeichert sind. Manipulierte Datenbankdokumente könnten andernfalls unerwartete Klassen instanziieren (Object-Injection-ähnliches Risiko).

Rückgabetyp von bsonSerialize(): Ab MongoDB PHP-Bibliothek 1.7 kann bsonSerialize() auch ein MongoDB\Model\BSONDocument zurückgeben. Für einfache Fälle ist ein Array ausreichend.