2009-08-11 1 views
5

Недавно я начал использовать Zend Framework (1.8.4), чтобы предоставить инструменты администратора для просмотра заказов сайта корзины покупок.Zend: два объекта, одна строка

Что я хотел бы сделать, так это эффективно создать несколько объектов модели() из единственной строки результатов базы данных.

Взаимоотношения просты: a Заказ имеет одного Заказчика (внешний ключ order_custid=customer.cust_id); Клиент имеет много ордеров.

Загрузка заказов достаточно проста. Используя метод документированного здесь:

Modeling objects with multiple table relationships in Zend Framework

... Я мог бы захватить клиент для каждого.


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

Но когда вы загружаете длинный список заказов - скажем, 40 или более, pageful - это мучительно медленно.

Далее я попробовал 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); 

Это дает мне массив объектов порядка. print_r($orders) показывает, что каждый из них содержит список столбцов, который я ожидаю в защищенном члене, с именами необработанных полей order_ * и cust_ *.

Но как создать объект Customer из полей cust_ *, которые я нахожу в каждом из объектов Order?


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. 

} 

Есть ли хороший способ создать заказ и объект-клиент одновременно из объединенных строк? Или я должен запустить запрос без табличного шлюза, получить исходный набор результатов и скопировать каждое из полей по одному на вновь созданные объекты?

+0

Насколько я знаю, Zend_Db этого не делает. Меня тоже очень интересовало бы решение. – markus

ответ

1

Zend_Db не предоставляет удобные способы для этого.

Гипотетически, было бы неплохо использовать шаблон Фасад для строк, которые производятся из нескольких таблиц. Класс фасада будет отслеживать, какие столбцы принадлежат каждой соответствующей таблице. Когда вы устанавливаете отдельное поле или целую кучу полей с помощью метода setFromArray(), фасад будет знать, как сопоставлять поля с объектами Row для каждой таблицы и применять операторы UPDATE к затронутым таблицам.

В качестве альтернативы вы можете обойти проблему неизвестных полей путем подкласса Zend_Db_Table_Row_Abstract, изменив поведение __set(), чтобы молча игнорировать неизвестные столбцы, а не бросать исключение.

У вас не может быть OO-интерфейса, чтобы сделать все, что может сделать SQL. В песке должна быть какая-то строка, на которой вы решите, что был рассмотрен разумный набор распространенных случаев, и что-то более сложное должно быть сделано с SQL.

+0

Hibernate (Java) делает это элегантно; если вы это сделаете: query.addEntity (Order.class) query.addEntity (Customer.class); ... тогда вы возвращаетесь к списку, каждая строка которого представляет собой массив с этими двумя типами объектов в указанном порядке. –

+0

Это круто. Но для чего это стоит, Hibernate состоит из> 490 000 строк кода Java. Zend_Db составляет около 2700 строк кода PHP. Из-за среды выполнения PHP-платформы она более чувствительна к раздуванию кода, и поэтому более важно, чтобы библиотеки были скудными, применяя только к наиболее часто используемым функциям. –

+0

Хороший вопрос! Да, я вижу необходимость держать размер рамки в разумных пределах. –

1

Я использую этот метод для присвоения полей строки базы данных объектам. Я использую методы setter, но это, вероятно, также можно было бы сделать только с объектами.

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