我在集合中看到一个意想不到的行为,也许有人可以启发我(或者可能是一些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')
正如你所看到的,每次循环时,另外一个“AND(order_item_id =”为我正在过滤的每个项目ID添加。我认为每次循环,我都会得到一个新的版本使用$ order-&gt; getInvoiceCollection()。
的集合那么,有人能告诉我示例代码中出了什么问题并教会我正确的方法吗?
谢谢!
答案 0 :(得分:0)
关于您的业务问题:需要更多信息。目标是生成具有订单项对象的集合,这些对象是EACH了解发票和装运详细信息的吗?似乎有渲染问题被推入建模问题。
关于select语句问题:Varien collections有一个优化,阻止他们多次访问存储后端。通过将_isCollectionLoaded
属性设置为true
,可以在DB collection个实例中实现此标准行为。
在您的情况下,发票集合实例是通过订单实例stored in a protected property创建的,immediately load()
ed是通过IteratorAggregate
创建的(通过foreach
调用)。因为您在每次迭代中使用相同的订单对象实例,所以您正在处理此已加载的发票集合实例,并且每次迭代都会有效地调用addFieldToFilter(/* next order id */)
,从而导致不断扩展的WHERE
子句。通过调用$order->reset()
可以轻松解决此特定优化问题。这让我们回到了一个突出的问题,即需要更好地理解目标,并且(可能)使用自定义集合或操纵集合来加入您需要的特定数据。