ページネーションをネイティブに使用してMagentoコレクションを反復処理することは可能ですか?


21

それが私が意味することは-行う方法があります:

$collection = $model->getCollection();
foreach ($collection as $item) { 
    $item->doStuff();
}

コレクションに10万行ある場合でも、MySQLから一度に1ページの行だけをロードし、裏で魔法のようにページ分割します。

Varien_Data_Collection_Db::load()それを見ることは可能だとは思えないが、ただ確認したかった。これは、一般的に必要なもののように思えます。

回答:


18

あなたは本当に使うべきです

Mage::getSingleton('core/resource_iterator')

この目的のために、純粋にあなたが言及したパフォーマンス上の理由のために存在します。

それ以外の場合は、ループを使用してわずかにエレガントなソリューションを使用できますsetPageSize-ここに良い例があります、https://stackoverflow.com/questions/3786826/how-to-loop-a-magento-collection


1
YOU SIR、紳士であり学者です。
kalenjordan

以下のための+1 setPageSizeそれはセマンティックだから。
-philwinkle

私が気づいたもう1つのことは、core/resource_iteratorソリューションが実際にmysqlクエリをページ分割しないことです。結果セット全体を一度にロードしますが、PHPコードで処理する行を一度に提供します。したがって、PHP内のメモリフォールトを回避しますが、結果セットが非常に大きい場合、ある時点でmysqlの最大パケットサイズをトリガーします。私はsetPageSize()
-kalenjordan

ええ、私はムアーポイントを追求するためにそれを省略しましたページ分割されたコレクションではなく、単一の製品のロードを本当に目指しました。しかし、それは基盤となるものでなければなりません。
ベン・レッサーニ-ソナシ

MySQLへのクエリをバッチ処理するだけでなく、個々のコレクションアイテムコールバックも提供する汎用バッチイテレータを実装しました。好奇心が強い
kalenjordan

5

私は同意するベンLessaniあなたが使用する必要のあるcore/iterator時に大きなコレクションに1行をロードするために、リソースのモデルを、可能な場合

ただし、制限があります。「addAttributeToSelectがcore / resource_iteratorで機能しない」で説明したように、属性値テーブルの値を含める必要がある場合、EAVモデルではうまく機能しません。

また、StackOverflowからのリンクされた例は、異なるクエリで同じクエリを繰り返すため、実際にはそれほど良くありませんLIMIT。複雑なクエリの場合、これはパフォーマンスの問題になる可能性がありますが、さらに重要なことは、間に新しい行が追加されると重複することです。

チャンクでコレクションを処理するより良い方法は、最初にすべてのIDをロードし、次にこれらのIDを実際のページングされたコレクションのフィルターとして使用することです。

製品の簡単な例:

$ids = Mage::getModel('catalog/product')
    ->getCollection()
    ->getAllIds();

$page = 1;
do {
    $collection = Mage::getModel('catalog/product')
        ->getCollection()
        ->addIdFilter($ids)
        ->setPageSize(100)
        ->setCurPage($page);

    $results = $collection->load();

    // do stuff ......

    $page++;

} while ($results->count());
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.