1

Question popped up here: Filter collection on checkout/cart

Why does a filtered $collection->getSize() returns correct value, but iterating over collection has more items?

  • three items are in cart
  • want to filter one by SKU
  • result should be only one item

Example code:

$items = Mage::getSingleton('checkout/cart')->getQuote()->getItemsCollection();
$items->addFieldToFilter('sku', 75782007);

Using var_dump($items->getSize()) correctly returns int 1, but ...

foreach ($items as $item) {
    var_dump($item->getSku());
}

... results in ... (why?)

string '75782007' (length=8)
string '32811969' (length=8)
string 'hdd006' (length=6)

Workaround:

$itemIds = $items->getAllIds();
foreach ($items as $item) {
    if (in_array($item->getId(), $itemIds)) {
        var_dump($item->getSku());
    }
}

... results in ...

string '75782007' (length=8)

Why is getSize() and getAllIds() correct, but does not fit to collection count?

2

There are methods on the collection used for iterating. getVisibleItms is different from getAllItems. Depending upon the type of product, it could actually be that this one product is made up of a group or selection of products. Bundled products are an example of this. You will see only one item in cart but in the raw data it will show multiple products.

  • Thanks for your answer. Have added 3 simple products to cart. Havent looked into code yet, but if i remember right getVisibleItms and getAllItems return array, no Varien_Data_Collection ... so it doesnt fit to the original question. – sv3n Jul 22 '17 at 20:26
1

You should always use the ORM methods as using PHPs count or looping over the collection is bad practice. The reasoning is most likely off by one errors, which you'll most likely find buried some where in the framework such as varien collection.

Details: http://info.magento.com/rs/magentocommerce/images/Conquer_the_5_Most_Common_Magento_Coding_Issues_to_Optimize_Your_Site_for_Performance.pdf

* EDIT * Link fixed.

Also the reasoning you'll find in the Varien_Data_Collection class, as I mentioned if you were wanting to iterate over the collection, you're much better off using an iterator like the class does as it's a part of the framework's ORM. most likely the one off is the fact that when getSize is called the returned value is set with intval into an integer. As a 0 will = false, on conditions, etc. Take a look at getLastPageNumber and it will make sense.

As for a much better means of iterations without running out of memory on large collections is: // Walk through collection, for large collections this is much faster than using foreach Mage::getSingleton('core/resource_iterator')->walk($collection->getSelect(), array('productUpdateCallback'));

Anyhow hopefully this explains it more.

  • Not really helpfull. I already use getSize() mehthod for performance reasons. Btw ... link is broken. – sv3n Jul 22 '17 at 8:41
  • Updated answer. – B00MER Jul 22 '17 at 13:43
  • Thanks for answering :) I know about this stuff and also use it ... foreach was just for testing , to check if addFieldToFilter works. Update question tomorrow ... – sv3n Jul 22 '17 at 20:29
1

Sorry B00MER, Brett for wasting your time ...

All is working as intended ...

Mage::getSingleton('checkout/cart')->getQuote()->getItemsCollection();

... just returns an already loaded collection that is stored in customer/session - so addFieldToFilter() has no affect here.

getSize() and getAllIds() gives "wrong" results because it does not count the items in that collection ... it's just runs another query to get number of rows or get the IDs where addFieldToFilter() is also applied.

So $items->getSize() returns 1, but count($items) still gives 3.

Maybe someone can confirm this explanation?

1

The difference between getSize() and count() is here Marius explanation

getSize() the collection is not loaded, count() it is, that why you get int(1) in getSize() and int(3) in count() .

  • This is already known and written in my answer. Btw ... this does not answer the questiom why its differnet for cart collection :) – sv3n Jul 22 '17 at 21:52
  • If you create a collection with Mage::getModel(catalog/product)->getCollection() result is equal for getSize() and count, just differs in execution time. See here: magento.stackexchange.com/questions/179028/…. But here (or more in your question) its not equal since collection is already loaded. Still +1 spending you time :P – sv3n Jul 22 '17 at 22:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.