2008-10-24 3 views
7

Die Situation ist wie folgt: Ich habe 2 Modelle: 'Aktion' und 'Benutzer'. Diese Modelle beziehen sich auf die Tabellen "Aktionen" bzw. "Benutzer".Automatisches Verbinden von Tabellen, ohne das Standardverhalten in Zend Framework zu stören

Meine Aktionstabelle enthält eine Spalte user_id. In diesem Moment brauche ich einen Überblick über alle Aktionen und die Benutzer, denen sie zugewiesen sind. Wenn ich $action->fetchAll() verwende, habe ich nur die Benutzer-ID, also möchte ich in der Lage sein, die Daten aus dem Benutzermodell beizutreten, vorzugsweise ohne einen Anruf an findDependentRowset().

Ich dachte über die Erstellung von benutzerdefinierten fetchAll(), fetchRow() und find() Methoden in meinem Modell, aber dies würde Standardverhalten zu brechen.

Was ist der beste Weg, um dieses Problem zu lösen? Jede Hilfe würde sehr geschätzt werden.

+0

Was mit Zend_Db_Table_Row :: findDependentRowset() falsch ist? –

+1

Ein Einwand gegen findDependentRowset() und findParentRow() ist, dass es weniger effizient ist, verwandte Zeilen nacheinander zu laden, als beide Tabellen mit einem JOIN abzufragen, wenn Sie von Anfang an wissen, dass Sie alle zugehörigen Zeilen benötigen. –

Antwort

14

I entworfen und implementiert die Tabellenbeziehungen verfügen in Zend Framework.

Mein erster Kommentar ist, dass Sie sowieso findDependentRowset() nicht verwenden würden - Sie würden findParentRow() verwenden, wenn die Aktion einen Fremdschlüsselverweis auf Benutzer hat.

$actionTable = new Action(); 
$actionRowset = $actionTable->fetchAll(); 
foreach ($actionRowset as $actionRow) { 
    $userRow = $actionRow->findParentRow('User'); 
} 

Edit: In der Schleife haben Sie jetzt einen $ actionRow und ein $ userRow Objekt. Sie können Änderungen über beide Objekte in die Datenbank zurückschreiben, indem Sie die Objektfelder ändern und save() für das Objekt aufrufen.

Sie können auch die Klasse Zend_Db_Table_Select verwenden (die implementiert wurde, nachdem ich das Projekt verlassen habe), um ein Rowset basierend auf einer Verknüpfung zwischen Aktion und Benutzer abzurufen.

Beachten Sie, dass ein solches Rowset basierend auf einer Join-Abfrage schreibgeschützt ist. Sie können in den Zeilenobjekten keine Feldwerte festlegen und save() aufrufen, um Änderungen zurück an die Datenbank zu senden.

Bearbeiten: Es gibt keine Möglichkeit, ein beliebiges verbundenes Ergebnissatz beschreibbar zu machen. ein einfaches Beispiel auf dem verbundenen Ergebnis basiert Erwägen oben gesetzt:

action_id action_type user_id user_name 
    1   Buy   1  Bill 
    2   Sell   1  Bill 
    3   Buy   2  Aron 
    4   Sell   2  Aron 

Next für die Zeile mit action_id = 1, I eines der Felder zu ändern, die von dem Benutzerobjekt kam:

$joinedRow->user_name = 'William'; 
$joinedRow->save(); 

Fragen: Wenn ich die nächste Zeile mit action_id = 2 ansehe, sollte ich "Bill" oder "William" sehen? Wenn "William", bedeutet dies, dass das Speichern von Zeile 1 automatisch "Bill" in allen anderen Zeilen dieses Ergebnissatzes auf "William" aktualisieren muss? Oder bedeutet es, dass save() automatisch die SQL-Abfrage erneut ausführt, um eine aktualisierte Ergebnismenge aus der Datenbank zu erhalten? Was ist, wenn die Abfrage zeitaufwendig ist?

Beachten Sie auch das objektorientierte Design. Jede Zeile ist ein separates Objekt. Ist es angebracht, dass das Aufrufen von save() auf einem Objekt den Nebeneffekt hat, Werte in einem separaten Objekt zu ändern (selbst wenn sie Teil derselben Objektgruppe sind)? Das scheint mir eine Form von Content Coupling zu sein.

Das obige Beispiel ist eine relativ einfache Abfrage, aber auch komplexere Abfragen sind zulässig. Zend_Db kann keine Abfragen mit der Absicht analysieren, beschreibbare Ergebnisse von schreibgeschützten Ergebnissen zu unterscheiden. Das ist auch der Grund, warum MySQL-Ansichten nicht aktualisierbar sind.

+0

Danke, deine Erklärung verdeutlicht die Situation; Ich gehe einfach mit einer benutzerdefinierten Methode, die ein schreibgeschütztes Objekt zurückgibt. –

+0

Ja, das ist eine gute Lösung. –

+0

+1 und Danke, ich war auf der Suche nach so etwas auch. Wäre cool, wenn ZF sowas wie RoRs 'find (: all,: includes)' hätte, obwohl – Gordon

2

Sie können immer eine Ansicht in Ihrer Datenbank erstellen, die die Verknüpfung für Sie ausführt.

CREATE OR REPLACE VIEW VwAction AS 
SELECT [columns] 
    FROM action 
    LEFT JOIN user 
    ON user.id = action.user_id 

Dann benutzen Sie einfach

$vwAction->fetchAll(); 

Denken Sie daran, dass die Ansichten in MySQL nur gelesen werden (vorausgesetzt, dies ist MySQL)

1

erstellt keine Ansicht sql Tabelle eine gute Lösung zu machen Joint? und nach einer einfachen Tabellenklasse, um es

greift ich denke, es wäre besser, wenn Sie Ihre Logik als in PHP in SQL ist