MongoDB Objekt-Mapping (PHP)

8

Einführungsproblem:

Was ist die beste Vorgehensweise, um mein Objekt class T zu erstellen, wenn ich es von einem MongoCursor::getNext() erhalte? Soweit es geht, gibt getNext() function eines MongoCursor mit einem array zurück. Ich möchte das Ergebnis von diesem Punkt als object vom Typ T verwenden.

Soll ich meinen eigenen Konstruktor für den Typ T schreiben, der ein array akzeptiert? Gibt es dafür generische Lösungen, zB wenn der Typ T extends G und G den Job rekursiv (für verschachtelte Dokumente) als regulären Weg ausführt.

Ich bin neu in MongoDB, und ich möchte meinen eigenen generischen Mapper mit einer netten Schnittstelle erstellen.

Kopfgeld:

  • Welches sind die möglichen Ansätze, Muster und welche das Konzept von MongoDB am besten aus der Sicht von PHP passen würde.
Dyin 23.05.2013, 14:28
quelle

1 Antwort

3

Diese Antwort wurde neu geschrieben.

Die meisten Datenmapper arbeiten, indem sie ein Objekt pro Klasse repräsentieren, oder "Modell" ist normalerweise der geprägte Begriff. Wenn Sie mehrere Zugriffe durch ein einzelnes Objekt zulassen möchten (zB $model->find() ), wird normalerweise die Demed-Methode ausgeführt, so dass die Methode nicht tatsächlich eine Instanz von sich selbst zurückgibt, sondern stattdessen die eines Arrays oder% .

Ein solches Paradigma ist normalerweise mit "Active Record" verbunden. Dies ist die Methode, die ORMs, ODMs und Frameworks verwenden, um mit Datenbanken auf die eine oder andere Weise zu kommunizieren, nicht nur für MongoDB, sondern auch für SQL und andere mögliche Datenbanken (Cassandra, CouchDB usw.).

>

Es sollte sofort darauf hingewiesen werden, dass, obwohl der aktive Datensatz eine Menge Macht hat, er nicht über die gesamte Anwendung verteilt sein sollte. Es gibt Zeiten, in denen die direkte Verwendung des Treibers vorteilhafter wäre. Die meisten ORMs, ODMs und Frameworks bieten die Möglichkeit, aus diesem Grund schnell und mühelos auf den Treiber zuzugreifen.

Es gibt, wie viele sagen würden, keinen leichten Datenmapper. Wenn Sie die zurückgegebenen Daten den Klassen zuordnen, werden Ende des Monats Ressourcen verbraucht. Der Vorteil dabei ist die Leistung, die Sie erhalten, wenn Sie Ihre Objekte manipulieren.

Active record ist wirklich gut darin, Ereignisse und Trigger innerhalb von PHP bereitstellen zu können. Ein gutes Beispiel ist das eines ORM, das ich für Yii gemacht habe: Ссылка es kann Hooks für Folgendes bereitstellen:

  • MongoCursor
  • afterConstruct
  • beforeFind
  • afterFind
  • beforeValidate
  • afterValidate
  • beforeSave

Es sollte angemerkt werden, dass MongoDB, wenn es um Ereignisse wie afterSave und beforeSave geht, keine Trigger besitzt ( Ссылка ), so dass es sinnvoll ist, dass die Anwendung damit umgehen sollte. Zusätzlich zu dem offensichtlichen Grund für die Anwendung, dies zu handhaben, macht es auch eine viel bessere Handhabung der Speicherfunktionen, indem es in der Lage ist, Ihre nativen PHP-Funktionen aufzurufen, jedes gespeicherte Dokument vor dem Berühren der Datenbank zu manipulieren.

Die meisten Data Mapper arbeiten mit der eigenen CRUD-Klasse von PHP, um auch diese darzustellen. Um beispielsweise einen neuen Datensatz zu erstellen:

%Vor%

Dies ist ein ziemlich guter Ansatz, da Sie ein "neues" ( Ссылка ) erstellen zeigt, wie ich mich auf einen neuen Rekord in MongoYii) Klasse vorbereite, um einen "neuen" Rekord zu machen. Es passt ziemlich gut semantisch.

Auf Update-Funktionen wird normalerweise über Lesefunktionen zugegriffen. Sie können ein Modell, dessen Existenz Ihnen nicht bekannt ist, nicht aktualisieren. Dies bringt uns auf den nächsten Schritt der Bestückung von Modellen.

Um mit dem Auffüllen eines Modells fertig zu werden, verpflichten sich verschiedene ORMs, ODMs und Frameworks zu verschiedenen Methoden. Zum Beispiel verwendet meine MongoYii-Erweiterung eine Factory-Methode namens afterSave in jeder Klasse, um eine neue Instanz von sich selbst zurückzuholen, so dass ich die dynamischen model und find und andere solche Methoden aufrufen kann.

Einige ORMs, ODMs und Frameworks stellen die Lesefunktionen als direkte findOne -Funktionen zur Verfügung, die sie selbst zu Factory-Methoden machen, während einige das Singleton-Muster verwenden, jedoch nicht ( Ссылка ).

Die meisten, wenn nicht alle, implementieren eine Form des Cursors. Dies wird verwendet, um ein Vielfaches der Modelle zurückzugeben, und umschließt (normalerweise) static , um die Methode MongoCursor durch die Rückgabe eines vorbelegten Modells zu ersetzen.

Zum Beispiel aufrufen:

%Vor%

Würde ein current() (in MongoYii) zurückgeben, was dann die Tatsache widerspiegelt, dass die Klasse EMongoCursor verwendet wurde, um den Cursor zu instanziieren und wenn er wie folgt aufgerufen wird:

%Vor%

Würde die Methode User hier aufrufen: Ссылка , die eine neue einzelne Instanz zurückgibt des Modells.

Es gibt einige ORMs, ODMs und Frameworks, die das Laden von Early-Arrays implementieren. Das bedeutet, dass sie das gesamte Ergebnis direkt als eine Reihe von Modellen in Ihren Arbeitsspeicher laden. Ich persönlich mag diesen Ansatz nicht, er ist verschwenderisch und verheißt nichts Gutes, wenn Sie für größere Updates Active Record verwenden müssen, weil Sie an Orten, an denen alte Datensätze hinzugefügt werden müssen, neue Funktionen hinzufügen.

Ein letztes Thema, bevor ich fortfahre, ist die schemalose Natur von MongoDB. Das Problem bei der Verwendung von PHP-Klassen mit MongoDB ist, dass Sie alle Funktionen von PHP, aber mit der variablen Natur von MongoDB haben wollen. Dies ist in SQL leicht zu überwinden, da es ein vordefiniertes Schema hat, das Sie einfach abfragen und Jobs erledigen. MongoDB hat jedoch keine solche Möglichkeit.

Dies macht die Handhabung von Schemas in MongoDB ziemlich gefährlich. Die meisten ORMs, ODMs und Frameworks verlangen, dass Sie das Schema im Spot (d. H. Doctrine 2) vordefinieren, indem Sie current() variables mit den Methoden private und get verwenden.In MongoYii, um mein Leben einfach und elegant zu machen, entschied ich mich dafür, die schemalose Natur von MongoDB zu behalten, indem ich Zauber einsetzte, die ( Ссылка ist mein set und Ссылка ist meine __get ), wenn die Eigenschaft in der Klasse nicht verfügbar war, wenn das Feld in einem internen __set -Array war und wenn nicht, dann gebe _attributes zurück. Ebenso würde ich zum Setzen eines Attributs einfach die interne null Variable setzen.

Was die Zuweisung dieses Schemas betrifft, habe ich die interne Zuweisung dem Benutzer überlassen, aber um die Eigenschaften von Formularen usw. zu bestimmen, habe ich die Validierungsregeln verwendet ( Ссылка ) eine Funktion mit dem Namen _attributes aufrufen, die eine Liste von Attributen zurückgibt, für die Validierungsregeln gelten. Wenn sie keine Validierungsregeln hätten, würden diese Attribute, die im ankommenden Array getSafeAttributeNames() oder $_POST existierten, nicht gesetzt sein. Dies bot die Möglichkeit für eine Schema- und dennoch sichere Modellstruktur.

So haben wir behandelt, wie Sie das root-Dokument tatsächlich verwenden. Sie fragen auch, wie Data Mapper Filialdokumente handhaben. Lehre 2 und viele andere bieten vollständige klassenbasierte Filialdokumente ( Ссылка ), aber das kann sehr einfallsreich sein. Stattdessen entschied ich, dass ich Hilfsfunktionen bereitstellen würde, die eine flexible Verwendung von Filialdokumenten ermöglichen würden, ohne sie eifrig in Modelle zu laden und so RAM zu verbrauchen. Im Grunde genommen habe ich sie verlassen, da sie einen Validator stellen ( Ссылка ) um innerhalb von ihnen zu validieren. Natürlich erzeugt der Validator selbst. Wenn Sie also eine Validierungsregel im Validator haben, die den Validator erneut verwendet, um eine Validierung eines verschachtelten Filialdokuments auszugeben, würde es funktionieren.

So denke ich , dass eine sehr grundlegende Diskussion über ORMs, ODMs und Frameworks mit Data Mappers abgeschlossen wird. Natürlich könnte ich wahrscheinlich einen ganzen Essay darüber schreiben, aber das ist eine Diskussion genug für die Minute, glaube ich.

    
Sammaye 23.05.2013, 14:34
quelle

Tags und Links