0

我在集合中看到了一个意想不到的行为,也许有人可以启发我(或者可能是我不了解的一点 PHP)(抱歉这篇文章的长度,但我必须包含示例代码和结果)。

我的目标是编写一份报告,在其中获得订单及其订单商品,然后转到订单的发票和发货数据,并从他们的商品中获取匹配的订单商品数据。我知道所有订单只有一张发票和发货,所以即使 Magento 在订单和发票/发货之间使用 1-M 关系,我也可以像 1-1 一样利用它

我知道这些项目都是使用 order_item_id 字段相关的,所以我尝试编写一个使用以下调用的函数 -

$invoiceItem = $order
  ->getInvoiceCollection()
  ->getFirstItem()
  ->getItemsCollection()
  ->addFieldToFilter('order_item_id', $orderItem->getItemId())
  ->getFirstItem();

但这不是我预期的结果,我看到的是无论过滤器中使用的订单项目 ID 是什么,都返回了相同的发票项目。

因此,为了尝试理解问题,我编写了以下小程序来查看查询是如何创建的。

<?php

require dirname(__FILE__).'/../app/Mage.php';    
umask(0);
Mage::app('default');

$orders = Mage::getResourceModel('sales/order_collection')
       ->addAttributeToSelect('*')
       ->addAttributeToFilter('state', 'processing') 
       ->addAttributeToSort('created_at', 'desc')
       ->addAttributeToSort('status', 'asc')
       ->load();

foreach ($orders as $order) {

    echo "\ngetting data for order id ". $order->getId();

    $items = $order->getAllItems();
    $invoice = $order->getInvoiceCollection()->getFirstItem();

    foreach ($items as $orderItem) {

        echo "\n\ngetting data for order item id ". $orderItem->getItemId();    
        $invoiceItems = $order
                   ->getInvoiceCollection()
                   ->getFirstItem()
                   ->getItemsCollection()
                   ->addFieldToFilter('order_item_id', $orderItem->getItemId());    
        echo "\n".$invoiceItems->getSelect();    
    }
    die;  //just quit after one iteration
}

该程序的输出如下 -

getting data for order id 7692

getting data for order item id 20870
SELECT `main_table`.* FROM `sales_flat_invoice_item` AS `main_table` WHERE (parent_id = '7623') AND (order_item_id = '20870')

getting data for order item id 20871
SELECT `main_table`.* FROM `sales_flat_invoice_item` AS `main_table` WHERE (parent_id = '7623') AND (order_item_id = '20870') AND (order_item_id = '20871')

getting data for order item id 20872
SELECT `main_table`.* FROM `sales_flat_invoice_item` AS `main_table` WHERE (parent_id = '7623') AND (order_item_id = '20870') AND (order_item_id = '20871') AND (order_item_id = '20872')

如您所见,每次通过循环时,都会为我过滤的每个项目 ID 添加另一个“AND(order_item_id =”。我认为每次通过循环,我都会从使用 $order->getInvoiceCollection()。

那么,谁能告诉我我的示例代码出了什么问题,并教育我正确的方法来做到这一点?

谢谢!

4

1 回答 1

0

关于您的业务问题:需要更多信息。目标是生成一个包含每个都知道发票和发货详细信息的订单项目对象的集合吗?似乎有渲染问题被推入建模问题。

关于 select 语句问题:Varien 集合有一个优化,可以防止它们多次访问存储后端。通过将属性设置为 ,可以在DB 集合实例中实现此标准行为。_isCollectionLoadedtrue

在您的情况下,发票收集实例是通过存储在受保护属性中的订单实例创建的,并立即load()通过IteratorAggregate(通过调用)进行编辑foreach。因为您在每次迭代中使用相同的订单对象实例,所以您正在处理这个加载的发票集合实例,并且在addFieldToFilter(/* next order id */)每次迭代中有效地调用,从而导致不断扩展的WHERE子句。这个特定的优化可以很容易地通过调用来解决$order->reset()。不过,这让我们回到了突出的问题,即需要更好地理解目标并(可能)使用自定义集合或操作集合以加入您需要的特定数据。

于 2012-12-07T13:51:08.647 回答