Можно ли перебирать коллекции Magento с разбиением на страницы изначально?


Что я имею в виду под этим - есть ли способ сделать:

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

Таким образом, что даже если бы в коллекции было 100 тысяч строк, она загружала бы только страницу строк за раз из MySQL и волшебным образом разбивала их на страницы для вас за кулисами.

Глядя на Varien_Data_Collection_Db::load(), кажется, что это невозможно, но я просто хотел проверить. Это похоже на то, что должно быть общей потребностью.

Author: kalenjordan, 2013-04-16

2 answers

Вам действительно следует использовать

Mage::getSingleton('core/resource_iterator')

Для этой цели, поскольку она существует исключительно по причинам производительности, о которых вы упомянули.

В противном случае вы можете использовать несколько менее элегантное решение, используя цикл с setPageSize - здесь есть хороший пример, https://stackoverflow.com/questions/3786826/how-to-loop-a-magento-collection

 18
Author: Ben Lessani - Sonassi, 2017-05-23 12:37:16

Я согласен с Бен Лессани, что вам следует использовать модель ресурсов core/iterator для загрузки больших коллекций по одной строке за раз , если это возможно.

Однако существуют ограничения. Как объяснено в "addattributetoselect не работает с core/resource_iterator?" это плохо работает с моделями EAV, если вам нужно включить значения из таблиц значений атрибутов.

И связанный пример из StackOverflow на самом деле не так хорош, потому что он повторяет то же самое запрос с различными выражениями LIMIT. Для сложных запросов это может быть проблемой с производительностью, но что еще более важно, вы получите дубликаты, если между ними будут добавлены новые строки.

Лучший способ обработки коллекций по частям - сначала загрузить все идентификаторы, а затем использовать эти идентификаторы в качестве фильтра для фактической выгружаемой коллекции.

Простой пример для продуктов:

$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());
 6
Author: Fabian Schmengler, 2017-04-13 12:55:02