2014-09-27 14 views
9

Ich bin neu in Symfony and Doctrine.Symfony2/Doctrine2 - ManyToOne - Inverse Seite speichern

Ich habe eine Entität "Benutzer" und eine Entität "Typ". Ein Benutzer kann einen Favoritentyp haben und ein Typ kann viele Benutzer haben, die diesen bestimmten Typ als Favorit haben. Also brauche ich eine Viele (User) to One (Type) Beziehung.

Ich habe es implementiert und es funktioniert gut (meistens). Aber eine Sache verstehe ich nicht.

Wenn ich etwas tun so funktioniert es:

$user = new User(); 
$type = new Type(); 

$user->setFavoriteType($type); 
$em->persist($user); 
$em->persist($type); 
$em->flush(); 

Die Objekte werden erzeugt und an die DB gespeichert. Und die favorite_type_id ist korrekt eingestellt. So Ändern der Eigentümerseite funktioniert wie erwartet.

Aber wenn ich den Benutzer der inversen Seite hinzufügen (nur) und den Entity Manager leeren die favorite_type_id ist nicht festgelegt.

$user = new User(); 
$type = new Type(); 

$type->getUsers()->add($user); //same with $type->addUser($user); 
$em->persist($user); 
$em->persist($type); 
$em->flush(); 

Warum ist das? Gibt es einen Grund, warum es nicht von der umgekehrten Seite funktioniert? Muss ich das wirklich manuell einstellen? Wenn ich die addUser-Methode in der Typ-Entity wie "$ user-> setFavoriteType ($ this)" manipuliere, funktioniert es. Aber sollte das nicht die Aufgabe der Lehre sein?

Die Dokumentation sagt

Wenn eine bidirektionale Assoziation aktualisiert wird, nur Lehre prüft auf einer der beiden Seiten für diese Veränderungen. Dies wird die Eigentümerseite des Vereins genannt.

So scheint es das gewünschte Verhalten zu sein, ist das richtig? Aber warum? Aufgrund der Leistung? Semantische Gründe?

Ich wäre froh, wenn mir jemand das erklären könnte oder mir sagen könnte, was ich falsch mache.

+0

Interessante Frage, ich bin auch neugierig auf die Wahl hinter dieser Logik. – DonCallisto

+0

http://doctrine-orm.readthedocs.org/en/latest/reference/unitofwork-associations.html – DonCallisto

+0

Können Sie uns die zugehörigen Entitäten zeigen? – ReynierPM

Antwort

3

Überprüfen Sie die Doctrine documentation on cascading.. Dies sollte Ihnen helfen, schnell und einfach mit dem zu beginnen, was Sie wollen, indem Sie cascade={"persist"} hinzufügen und Ihren Cache löschen (um Doctrines Metadaten-Cache neu zu erstellen).

0

Dies kommt zustande, weil Doctrine bei der Betrachtung der Persistenz grundsätzlich PHP-Entitäten direkt in Datenbanktabellen einbindet. In Ihrem Fall haben Benutzer und Typen konzeptionell eine Viele-zu-Eins-Beziehung, aber auf Datenbankebene wird die Beziehung vollständig in der Benutzertabelle dargestellt - ein Benutzer hat einen bevorzugten Typ, und daher hat die Benutzertabelle eine Spalte favorite_type_id. Obwohl wir uns vorstellen können, dass Typ-Entitäten eine Liste von Benutzern haben, für die sie der Favorit sind, wird dies im Wesentlichen auch durch das Betrachten der Tabelle Benutzer abgeleitet, da in der Tabelle Typ nichts enthalten ist.

Das Einrichten der Entitätszuordnung in Doctrine teilt Doctrine die Beziehung zwischen den Entitäten mit und ermöglicht es Doctrine, Ihnen bestimmte bequeme Zugriffsmethoden wie $type->getUsers() bereitzustellen, ändert jedoch nicht, wie die zugrunde liegenden Daten gespeichert werden. Wenn ich $user->setFavoriteType benutze, manipuliere ich Daten, für die es eine direkte Datenbankkorrespondenz gibt, aber standardmäßig, wenn ich rufe, bin ich nicht - der Hauptzweck, diese Art von Anruf out-of-the-box zu machen, ist die hydratisierte Entitäten, mit denen du gerade arbeitest, ohne die Objekte einfach wegwerfen und wieder aus der DB holen zu müssen.

Natürlich haben Sie gesehen, dass Sie addUser anpassen können, um auch setFavoriteType zu nennen, oder konfigurieren Sie Kaskadenpersistenz, wie Shon M vorschlägt, um das Verhalten ein bisschen mehr zu machen, wie Sie es erwarten/wollen. Es mag wie eine Zeitverschwendung erscheinen, das von vornherein auszulassen, aber ich vermute, dass die Doktrine-Entwickler bewusst die einfachste Funktionalität gewählt haben, um die benötigte Funktionalität zu implementieren, während sie mehrere einfache Alternativen bieten, wenn es das ist, wonach Sie suchen und damit für jeden etwas bieten. Ob es nun geht oder nicht, welche Daten in der DB sind und welche Daten in PHP nach der Hydration laufen, sind technisch unterschiedliche Dinge, besonders in einem Modell wie Doctrine, wo DB-Aktivitäten aufgeschoben werden, bis der Entwickler sie anfordert, und das macht sehr viel Sinn um all das so explizit wie möglich zu machen!