Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zend: Two Objects, one Row

I've recently started using Zend Framework (1.8.4), to provide admin tools for viewing the orders of a shopping cart site.

What I'd like to do is to efficiently create multiple model (Zend_Db_Table_Row_Abstract) objects from a single database result row.

The relationship is simple: an Order has one Customer (foreign key order_custid=customer.cust_id); a Customer has many Orders.

Loading the orders is easy enough. Using the method documented here:

Modeling objects with multiple table relationships in Zend Framework

...I could then grab the customer for each.


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

But when you're loading a long list of orders - say, 40 or more, a pageful - this is painfully slow.

Next I tried a 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);

This gives me an array of order objects. print_r($orders) shows that each of them contains the column list I expect, in a protected member, with raw field names order_* and cust_*.

But how to create a Customer object from the cust_* fields that I find in each of those Order objects?


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.

}

Is there any good way to create an Order and a Customer object simultaneously from the joined rows? Or must I run the query without the table gateway, get a raw result set, and copy each of the fields one-by-one into newly created objects?

like image 289
Matt Hucke Avatar asked Nov 05 '22 20:11

Matt Hucke


1 Answers

Zend_Db doesn't provide convenience methods to do this.

Hypothetically, it'd be nifty to use a Facade pattern for rows that derive from multiple tables. The facade class would keep track of which columns belong to each respective table. When you set an individual field or a whole bunch of fields with the setFromArray() method, the facade would know how to map fields to the Row objects for each table, and apply UPDATE statements to the table(s) affected.

Alternatively, you could work around the problem of unknown fields by subclassing Zend_Db_Table_Row_Abstract, changing the __set() behavior to silently ignore unknown columns instead of throwing an exception.

You can't have an OO interface to do everything SQL can do. There must be some line in the sand where you decide a reasonable set of common cases have been covered, and anything more complex should be done with SQL.

like image 57
Bill Karwin Avatar answered Nov 12 '22 21:11

Bill Karwin