0

コレクションで予期しない動作が見られます。誰かが教えてくれるかもしれません (または、私が理解していない PHP のビットかもしれません) (この投稿が長くなって申し訳ありませんが、サンプル コードと結果を含める必要がありました)。

私の目標は、注文とその注文アイテムを取得するレポートを作成し、注文の請求書​​と出荷データに移動して、それらのアイテムから一致する注文アイテム データを取得することでした。すべての注文に対して請求書と出荷が 1 つしかないことを知っているので、Magento は注文と請求書/出荷の間に 1 対 1 の関係を使用していますが、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->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 に答える