5

我最近开始使用 Zend Framework (1.8.4),为查看购物车网站的订单提供管理工具。

我想做的是Zend_Db_Table_Row_Abstract从单个数据库结果行有效地创建多个模型()对象。

关系很简单:一个订单有一个客户(外键order_custid=customer.cust_id);一个客户有很多订单。

加载订单很容易。使用此处记录的方法:

在 Zend Framework 中对具有多个表关系的对象进行建模

...然后我可以抓住每个客户。


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

但是,当您加载一长串订单时——比如说,40 个或更多,一页——这会非常缓慢。

接下来我尝试了一个 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_*。

但是如何从我在每个 Order 对象中找到的 cust_* 字段创建一个 Customer 对象?


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.

}

有没有什么好方法可以从连接的行同时创建一个 Order 和一个 Customer 对象?或者我必须在没有表网关的情况下运行查询,获取原始结果集,然后将每个字段一一复制到新创建的对象中?

4

2 回答 2

1

Zend_Db不提供方便的方法来做到这一点。

假设,对从多个表派生的行使用Facade模式会很不错。外观类将跟踪哪些列属于每个相应的表。当您使用该方法设置单个字段或一大堆字段时setFromArray(),外观将知道如何将字段映射到每个表的 Row 对象,并将UPDATE语句应用于受影响的表。

或者,您可以通过子类化来解决未知字段的问题Zend_Db_Table_Row_Abstract,将__set()行为更改为静默忽略未知列而不是引发异常。

您不能拥有一个 OO 接口来完成 SQL 可以做的所有事情。一定有一条线,您决定已经涵盖了一组合理的常见案例,并且应该使用 SQL 完成任何更复杂的事情。

于 2009-08-11T21:58:48.680 回答
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;
}
于 2009-08-11T19:58:07.550 回答