Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento: paginate filtered product collection

Tags:

php

magento

i want to filter and paginate a product collection. everything is fine - except pagination. im just getting the whole collection back, instead of 3 items for the first page.

    //fetch all visible products
    $product_collection = Mage::getModel('catalog/product')->getCollection();

    //set wanted fields (nescessary for filter)
    $product_collection->addAttributeToSelect('name');
    $product_collection->addAttributeToSelect('description');
    $product_collection->addAttributeToSelect('price');
    $product_collection->addAttributeToFilter('visibility', array('neq' => 1));

    //filter by name or description
    $product_collection->addFieldToFilter(array(
          array('attribute'=>'name','like'=>$sTerm),
          array('attribute'=>'description','like'=>$sTerm)
    ));

    //filter for max price
    foreach ($product_collection as $key => $item) {
        if($item->getPrice() >= $priceTo){
             $product_collection->removeItemByKey($key);
        }
    }

    //pagination (THIS DOESNT WORK!)
    $product_collection->setPageSize(3)->setCurPage(1);

    //TEST OUTPUT
    foreach ($product_collection as $product) {
          echo $product->getName().'<br />';
    }

thanks for your support!

like image 338
Daniel Schönherr Avatar asked Feb 03 '12 13:02

Daniel Schönherr


2 Answers

You are so close! Try moving that $product_collection->setPageSize(3)->setCurPage(1); line before the first foreach() iteration over the collection.

Magento collections are lazy-loaded. Until you directly load() them (or implicitly load them via a call to count() or foreach()) you can modify the collection properties which affect the underlying query (EDIT: see note below). Once the collection has been loaded explicitly or implicitly though you will only get the members of the _items property that have been set.

FYI you can call clear() to leave the original query-affecting properties (filters, sorters, limits, joins, etc) in place and then add further properties.

HTH

EDIT: Actually, adjusting query properties is always possible regardless of _items load state, but the effect won't be visible until the collection is regenerated.

like image 200
benmarks Avatar answered Oct 05 '22 11:10

benmarks


Thanks @Ben! You gave me the right hint. Now it does work! Basically I'm creating another collection and filter this one by the ids of the already filtered items. Afterwards its easy to add pagination to that new collection. That's the working code:

    //fetch all visible products
    $product_collection = Mage::getModel('catalog/product')->getCollection();

    //set wanted fields (nescessary for filter)
    $product_collection->addAttributeToSelect('name');
    $product_collection->addAttributeToSelect('description');
    $product_collection->addAttributeToSelect('price');
    $product_collection->addAttributeToFilter('visibility', array('neq' => 1));

    //filter by name or description
    $product_collection->addFieldToFilter(array(
          array('attribute'=>'name','like'=>$sTerm),
          array('attribute'=>'description','like'=>$sTerm)
    ));

    //filter for max price
    foreach ($product_collection as $key => $item) {
        if($item->getPrice() >= $priceTo){
             $product_collection->removeItemByKey($key);
        }
    }

    //build id array out of filtered items (NEW!)
    foreach($product_collection as $item){
        $arrProductIds[]=$item->getId();
    }

    //recreate collection out of product ids (NEW)
    $product_filtered_collection = Mage::getModel('catalog/product')->getCollection();
    $product_filtered_collection->addAttributeToFilter('entity_id', array('in'=>$arrProductIds));


    //add pagination (on new collection) (NEW)
    $product_filtered_collection->setPageSize(3)->setCurPage(1);


    //TEST OUTPUT
    foreach ($product_filtered_collection as $product) {
          echo $product->getName().'<br />';
    }
like image 43
Daniel Schönherr Avatar answered Oct 05 '22 10:10

Daniel Schönherr