2009-08-11 5 views
5

Ich habe vor kurzem begonnen, Zend Framework (1.8.4) zu verwenden, um Admin-Tools zum Anzeigen der Bestellungen einer Warenkorb-Website bereitzustellen.Zend: Zwei Objekte, eine Zeile

Ich möchte effizient mehrere Modellobjekte (Zend_Db_Table_Row_Abstract) aus einer einzelnen Datenbankergebniszeile erstellen. Die Beziehung ist einfach: eine Bestellung hat einen Kunden (Fremdschlüssel order_custid=customer.cust_id); ein Kunde hat viele Bestellungen.

Das Laden der Bestellungen ist einfach genug. die Methode hier dokumentiert werden:

Modeling objects with multiple table relationships in Zend Framework

... Ich kann dann die Kunden für jeden greifen.


    foreach ($orderList as $o) 
    { 
     cust = $o->findParentRow('Customers'); 
     print_r ($cust); // works as expected. 
    } 

Aber wenn Sie eine lange Liste von Aufträgen Laden - sagen wir, 40 oder mehr, ein pageful - das ist schmerzlich langsam.

Weiter habe ich versucht, eine JOIN:


    $custTable = new Customers(); 
    $orderTable = new Orders(); 
    $orderQuery = $orderTable->select() 
     ->setIntegrityCheck(false) // allows joins 
     ->from($orderTable) 
     ->join('customers', 'cust_id=order_custid') 
     ->where("order_status=?", 1); //incoming orders only. 
    $orders = $orderTable->fetchAll($orderQuery); 

Das ist mir eine Reihe von Auftragsobjekten gibt. print_r($orders) zeigt, dass jeder von ihnen die Spaltenliste enthält, die ich in einem geschützten Member mit den rohen Feldnamen order_ * und cust_ * erwarte.

Wie aber ein Customer-Objekt aus den cust_ * -Feldern, die ich in jedem dieser Order-Objekte finde, zu erstellen?


foreach ($orders as $o) { 
    $cols = $o->toArray(); 
    print_r ($cols); // looks good, has cust_* fields... 

    $cust = new Customer(array('table' => 'Customer', 'data' => $cols)); 
    // fails - $cust->id, $cust->firstname, etc are empty 

    $cust->setFromArray($cols); 
    // complains about unknown 'order_' fields. 

} 

Gibt es eine gute Möglichkeit, ein Auftrags- und ein Kundenobjekt gleichzeitig aus den verknüpften Zeilen zu erstellen? Oder muss ich die Abfrage ohne das Tabellen-Gateway ausführen, ein Rohergebnis erhalten und jedes der Felder eins nach dem anderen in neu erstellte Objekte kopieren?

+0

Soweit ich weiß Zend_Db macht das nicht. Ich wäre auch sehr an einer Lösung interessiert. – markus

Antwort

1

Zend_Db bietet keine Komfortmethoden, um dies zu tun.

Hypothetisch wäre es geschickt, ein Facade Muster für Zeilen zu verwenden, die von mehreren Tabellen abgeleitet sind. Die Fassadenklasse würde verfolgen, welche Spalten zu der jeweiligen Tabelle gehören. Wenn Sie ein einzelnes Feld oder eine ganze Reihe von Feldern mit der Methode setFromArray() festlegen, weiß die Fassade, wie Felder den Zeilenobjekten für jede Tabelle zugeordnet werden, und wendet die Anweisungen UPDATE auf die betroffenen Tabellen an.

Alternativ können Sie das Problem unbekannter Felder umgehen, indem Sie Zend_Db_Table_Row_AbstractZend_Db_Table_Row_Abstract abwandeln, das Verhalten __set() ändern, um unbekannte Spalten stillschweigend zu ignorieren, anstatt eine Ausnahme zu werfen.

Sie können keine OO-Schnittstelle haben, um alles zu tun, was SQL tun kann. Es muss eine Linie im Sand geben, in der Sie entscheiden, dass eine vernünftige Menge von allgemeinen Fällen behandelt wurde, und etwas Komplexeres sollte mit SQL gemacht werden.

+0

Hibernate (Java) macht es elegant; Wenn Sie dies tun: query.addEntity (Order.class) query.addEntity (Customer.class); ... was Sie zurückbekommen, ist eine Liste, wobei jede Zeile ein Array mit diesen beiden Objekttypen in der angegebenen Reihenfolge ist. –

+0

Das ist cool. Aber für was es wert ist, besteht Hibernate aus> 490.000 Zeilen Java-Code. Zend_Db ist etwa 2.700 Zeilen PHP-Code. Aufgrund der Laufzeit der PHP-Plattform ist sie sensibler für Code-Bloat. Daher ist es wichtiger, die Bibliotheken schlank zu halten, indem nur die am häufigsten verwendeten Funktionen implementiert werden. –

+0

Guter Punkt! Ja, ich sehe die Notwendigkeit, eine Rahmengröße im Rahmen des Zumutbaren zu halten. –

1

Ich verwende diese Methode, um Datenbankzeilenfelder Objekten zuzuordnen. Ich benutze Setter-Methoden, aber das könnte wahrscheinlich auch nur mit Eigenschaften für Objekte geschehen.

public function setOptions(array $options){ 
    $methods = get_class_methods($this); 
    foreach ($options as $key => $value) { 
     $method = 'set' . ucfirst($key); 
     if (in_array($method, $methods)) { 
      $this->$method($value); 
     } 
    } 
    return $this; 
}