Чи можна повторити колекції Magento з пагінацією?


21

Що я маю на увазі під цим, - чи є спосіб зробити:

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

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

З огляду на Varien_Data_Collection_Db::load()це не здається, що це можливо, а просто хотілося перевірити. Це здається чимось, що має бути загальною потребою.

Відповіді:


18

Вам слід реально користуватися

Mage::getSingleton('core/resource_iterator')

для цієї мети, оскільки існує виключно з причин, які ви згадали.

В іншому випадку ви можете використовувати трохи менш елегантне рішення, використовуючи петлю з setPageSize- тут є хороший приклад, /programming/3786826/how-to-loop-a-magento-collection


1
ВАМ СПІВ, джентльмен і науковець.
kalenjordan

+1, setPageSizeтому що це смислово.
philwinkle

Ще одна річ, яку я зрозумів - це те, що core/resource_iteratorрішення насправді не заподіює запит mysql. Він завантажує весь набір результатів одразу, але потім надає рядок за часом, з яким потрібно працювати у своєму PHP коді. Таким чином, це дозволяє уникнути помилок пам'яті в PHP, але в якийсь момент він запустить максимум розмірів пакетів mysql, якщо набір результатів дуже великий. Я думаю, що я спробую створити приємний абстрактний фрагмент resource_iterator за допомогоюsetPageSize()
kalenjordan

Так, я начебто пропустив це, переслідуючи два моменти! Її дійсно спрямовано на завантаження одного продукту порівняно зі стражданою колекцією. Але він повинен слугувати базою для розвитку.
Бен Лессані - Сонассі

Я реалізував загальний пакетний ітератор, який збирає запити до MySQL, але також надає індивідуальний зворотний виклик колекції. Цікаво, що ви думаєте: gist.github.com/kalenjordan/5483065
kalenjordan

5

Я погоджуюся з Бен Лессані, що вам слід використовувати 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());
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.