Ist es möglich, Magento-Sammlungen nativ mit Paginierung zu durchlaufen?

21

Was ich damit meine ist - gibt es eine Möglichkeit:

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

Selbst wenn die Sammlung 100.000 Zeilen hätte, würde sie immer nur eine Seite mit Zeilen aus MySQL laden und diese magisch für Sie hinter den Kulissen paginieren.

Auf den ersten Blick Varien_Data_Collection_Db::load()scheint es nicht möglich zu sein, sondern wollte es nur überprüfen. Dies scheint etwas zu sein, das ein allgemeines Bedürfnis sein sollte.

kalenjordan
quelle

Antworten:

18

Sie sollten wirklich verwenden

Mage::getSingleton('core/resource_iterator')

zu diesem Zweck, da es ausschließlich aus den von Ihnen genannten Leistungsgründen besteht.

Andernfalls können Sie eine etwas weniger elegante Lösung verwenden, indem Sie eine Schleife mit verwenden. Hier setPageSizefinden Sie ein gutes Beispiel: /programming/3786826/how-to-loop-a-magento-collection

Ben Lessani - Sonassi
quelle
1
SIE SIR, sind ein Gentleman und ein Gelehrter.
Kalenjordan
+1 für setPageSizeweil es semantisch ist.
Philwinkle
Eine andere Sache, die mir aufgefallen ist, ist, dass die core/resource_iteratorLösung die mysql-Abfrage nicht paginiert. Es lädt die gesamte Ergebnismenge auf einmal, gibt Ihnen dann aber jeweils eine Zeile, mit der Sie sich in Ihrem PHP-Code befassen müssen. Es vermeidet also Speicherfehler in PHP, löst aber irgendwann die maximale Paketgröße von mysql aus, wenn die Ergebnismenge sehr groß ist. Ich glaube, ich werde versuchen, mitsetPageSize()
kalenjordan am
Ja, ich habe das weggelassen, um Mwoar-Punkte zu erzielen! Es ist wirklich auf das Laden einzelner Produkte im Vergleich zu einer paginierten Sammlung ausgerichtet. Aber es sollte als Basis dienen, auf der man aufbauen kann.
Ben Lessani - Sonassi
Ich habe einen generischen Batch-Iterator implementiert, der die Abfragen an MySQL stapelt, aber auch einen Rückruf für einzelne Auflistungselemente bereitstellt. Neugierig, was Sie denken: gist.github.com/kalenjordan/5483065
kalenjordan
5

Ich stimme Ben Lessani zu, dass Sie das core/iteratorRessourcenmodell verwenden sollten, um große Sammlungen möglichst zeilenweise zu laden .

Es gibt jedoch Einschränkungen. Wie in " addAttributeToSelect funktioniert nicht mit core / resource_iterator? " Erläutert, funktioniert es nicht gut mit EAV-Modellen, wenn Sie Werte aus den Attributwerttabellen einbeziehen müssen.

Und das verknüpfte Beispiel von StackOverflow ist eigentlich nicht so gut, weil es die gleiche Abfrage mit unterschiedlichen LIMITAusdrücken wiederholt . Bei komplexen Abfragen kann dies ein Leistungsproblem darstellen. Noch wichtiger ist jedoch, dass Sie Duplikate erhalten, wenn neue Zeilen dazwischen hinzugefügt werden.

Eine bessere Möglichkeit, Sammlungen in Chunks zu verarbeiten, besteht darin, zuerst alle IDs zu laden und diese IDs dann als Filter für die tatsächlich ausgelagerte Sammlung zu verwenden.

Einfaches Beispiel für Produkte:

$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());
Fabian Schmengler
quelle