2009-08-11 18 views
5

Niedawno zacząłem używać Zend Framework (1.8.4), aby zapewnić narzędzia administracyjne do przeglądania zamówień na stronie koszyka.Zend: Dwa obiekty, jeden wiersz

Co chcę zrobić, to wydajnie utworzyć wiele obiektów modelu (Zend_Db_Table_Row_Abstract) z jednego wiersza wyników w bazie danych.

Relacja jest prosta: Zamówienie ma jednego Klienta (klucz obcy order_custid=customer.cust_id); Klient ma wiele Zamówień.

Ładowanie zamówień jest łatwe. Stosując metodę udokumentowany tutaj:

Modeling objects with multiple table relationships in Zend Framework

... Mógłbym wtedy złapać klienta dla każdego.


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

Ale kiedy ładujesz długą listę zamówień - powiedzmy, 40 lub więcej, strona - jest to boleśnie powolne.

Następny Próbowałem 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); 

To daje mi tablicę obiektów rzędu. print_r($orders) pokazuje, że każdy z nich zawiera listę kolumn, której oczekuję, w chronionym pliku, od surowych nazw pól order_ * i cust_ *.

Ale jak utworzyć obiekt klienta z pól cust_ *, które znajduję w każdym z tych obiektów zamówienia?


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. 

} 

Czy istnieje jakiś dobry sposób na utworzenie zamówienia i obiektu klienta jednocześnie z połączonych wierszy? Czy muszę uruchomić kwerendę bez bramy tabeli, uzyskać surowy zestaw wyników i skopiować każde z pól jeden po drugim do nowo utworzonych obiektów?

+0

Z tego co wiem, Zend_Db tego nie robi. Byłbym też bardzo zainteresowany rozwiązaniem. – markus

Odpowiedz

1

Zend_Db nie zapewnia wygodnych metod, aby to zrobić.

Hipotetycznie można użyć wzoru Fasada dla wierszy, które pochodzą z wielu tabel. Klasa elewacji będzie śledzić, które kolumny należą do poszczególnych tabel. Po ustawieniu pojedynczego pola lub całego zbioru pól metodą setFromArray(), fasada będzie wiedzieć, jak odwzorowywać pola na obiekty Row dla każdej tabeli i stosować instrukcje UPDATE do dotkniętych tabel (y).

Alternatywnie można obejść problem nieznanych pól, modyfikując podklasy Zend_Db_Table_Row_Abstract, zmieniając zachowanie __set(), aby po cichu zignorować nieznane kolumny, zamiast rzucać wyjątek.

Nie możesz mieć interfejsu OO, aby zrobić wszystko, co SQL może zrobić. Musi być pewna linia w piasku, gdzie zdecydujesz, że rozsądny zestaw typowych przypadków został omówiony, a wszystko, co jest bardziej skomplikowane, powinno zostać wykonane za pomocą SQL.

+0

Hibernate (Java) robi to elegancko; jeśli wykonasz: query.addEntity (Klasa zamówienia) query.addEntity (Customer.class); ... to, co otrzymasz, to Lista, której każdy wiersz jest tablicą z tymi dwoma typami obiektów w określonej kolejności. –

+0

To jest fajne. Ale za to, co jest warte, Hibernate składa się z> 490 000 linii kodu Java. Zend_Db to około 2700 linii kodu PHP. Ze względu na środowisko runtime platformy PHP, jest ona bardziej wrażliwa na nadpisywanie kodu, dlatego ważniejsze jest, aby biblioteki były szczupłe, wykorzystując tylko najczęściej używane funkcje. –

+0

Dobra uwaga! Tak, widzę potrzebę utrzymywania rozmiaru ramki w granicach rozsądku. –

1

Używam tej metody do przypisywania pól wierszy bazy danych do obiektów. Używam metod ustawiających, ale prawdopodobnie można to zrobić również tylko z właściwościami obiektu.

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; 
}