【问题标题】:Zend: Two Objects, one RowZend:两个对象,一行
【发布时间】:2010-11-18 17:23:56
【问题描述】:

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

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

关系很简单: 一个订单有一个客户(外键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 个或更多,一页),这会非常缓慢。

接下来我尝试了一个 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 对象?或者我必须在没有表网关的情况下运行查询,获取原始结果集,然后将每个字段一一复制到新创建的对象中?

【问题讨论】:

  • 据我所知 Zend_Db 不这样做。我也会对解决方案非常感兴趣。

标签: php zend-framework zend-db zend-db-table


【解决方案1】:

Zend_Db 没有提供方便的方法来执行此操作。

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

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

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

【讨论】:

  • Hibernate (Java) 优雅地做到了;如果你这样做: query.addEntity(Order.class) query.addEntity(Customer.class); ...那么你得到的是一个 List,其中的每一行都是一个数组,其中两个对象类型按指定的顺序排列。
  • 这很酷。但就其价值而言,Hibernate 包含超过 490,000 行 Java 代码。 Zend_Db 大约有 2,700 行 PHP 代码。由于 PHP 平台的运行时特性,它对代码膨胀更敏感,因此更重要的是使库精简,只实现最常用的功能。
  • 好点!是的,我可以看到需要将框架大小保持在合理范围内。
【解决方案2】:

我使用这种方法将数据库行字段分配给对象。我使用 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-03
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多