7

I am looping through products and getting an error with product images.

The code I am working with is below:

    <?php    
    $collection = Mage::getModel('catalog/product')->getCollection();
    $collection->addAttributeToFilter('status', 1); // 1=Enabled, 2=Disabled
    $obj = Mage::getModel('catalog/product');
    ?>
    <?php $productCounter=1; ?>
        <?php foreach ($collection as $product): ?>

            <?php $_productInCollection = $obj->load($product->entity_id); ?>

            <li class="item text-center">
                <a class="product-image" title="<?php echo $_productInCollection->getName(); ?>" href="<?php echo $_productInCollection->getProductUrl(); ?>">
                    <img src="<?php  echo $this->helper('catalog/image')->init($_productInCollection, 'small_image')->resize(null, 152)->keepFrame(false); ?>" height="152" alt="<?php echo $this->stripTags($this->getImageLabel($_productInCollection, 'small_image'), null, true) ?>" />
                 </a>
            </li>

            <?php if ($productCounter >=26) : ?>
                    <?php break; ?>
            <?php endif; ?>
            <?php $productCounter ++; ?>
        <?php endforeach; ?>

Attributes such as name are pulling through fine but I'm getting a strange error with product images. About 75% of the products I am working with do not have images so should show the default placeholder image, but I'm getting a strange pattern:

PRODUCT 1 -> has no image in admin panel -> SHOWS PLACEHOLDER (correct)
PRODUCT 2 -> has no image in ap -> SHOWS PLACEHOLDER (correct)
PRODUCT 3 -> has an image in ap -> SHOWS PRODUCT 3 IMAGE (correct)
PRODUCT 4 -> has no image in ap -> SHOWS PRODUCT 3 IMAGE (wrong, should show placeholder)
PRODUCT 5 -> has no image in ap -> SHOWS PRODUCT 3 IMAGE (wrong, should show placeholder)
PRODUCT 6 -> has no image in ap -> SHOWS PRODUCT 3 IMAGE (wrong, should show placeholder)
PRODUCT 7 -> has an image in ap -> SHOWS PRODUCT 7 IMAGE (correct)
PRODUCT 8 -> has no image in ap -> SHOWS PRODUCT 7 IMAGE (wrong, should show placeholder)
PRODUCT 9 -> has no image in ap -> SHOWS PRODUCT 7 IMAGE (wrong, should show placeholder)
PRODUCT 10 -> has an image in ap -> SHOWS PRODUCT 10 IMAGE (correct)

As soon as a product which has an image appears in the loop, that product appears fine, but if the next product in the loop has no image, it shows the previous product image rather than the placeholder. I have tried it with getImageUrl() too and the same pattern occurs.

I wonder if it is a caching problem or just that the image is not getting reset properly each time? Any help would be greatly appreciated, thank you!

I am using Magento ver. 1.7.0.2.

EDITED - SOLVED: Thanks to Marius below, this is the code I am using.

<?php    
    $collection = Mage::getModel('catalog/product')->getCollection();
    $collection->addAttributeToSelect('*');
    $collection->addAttributeToFilter('status', 1);
            // 1=Enabled, 2=Disabled
    $collection->getSelect()->limit(25);
    $productBlock=$this->getLayout()->createBlock("catalog/product");       
    ?>

    <?php $productCounter = 1; ?>

        <?php foreach ($collection as $product): ?>

            <?php if (($productCounter + 4) % 5 == 0) : ?>
               <ul class="products-grid">
            <?php endif; ?>

                     <li class="item text-center">
                                 <h3><?php echo $product->getName(); ?></h3>
                                 <img src="<?php  echo $this->helper('catalog/image')->init($product, 'small_image')->resize(null, 152)->keepFrame(false); ?>" height="152" alt="<?php echo $this->stripTags($this->getImageLabel($product, 'small_image'), null, true) ?>" />

                                 <?php echo $productBlock->getPriceHtml($product,true); ?>

                                 <a href="<?php echo $product->getProductUrl() ?>" title="<?php echo $product->getName(); ?>" class="more-info">
                                    More info
                                 </a>

                       </li>


            <?php if ($productCounter % 5 == 0 || $productCounter == $collection.length) : ?>
               </ul>
            <?php endif; ?>


        <?php endforeach; ?>
  • 4
    You should not be load()ing in a loop! Get the collection to load the attribute information which you need. – benmarks Oct 28 '13 at 11:40
9

First of all you shouldn't be using load in a loop. It's a really big performance killer. Use ->addAttributeToSelect('small_image') and after that use the $product object instead of $_productInCollection.
but if you really insist on using load use if as follows.

$_productInCollection = Mage::getModel('catalog/product')->load($product->entity_id);

if you use the same variable $obj for loading products you get issues like yours, because the objects are passed as reference.
So when you call $obj->load() the second time the variable $obj still contains the data from the first load and, and when calling load the data that is already set is merged with the new values from the database.
So...product 4 does not have an image, but $obj already has an image set from loading product 3. On merging you get the image from product 3.
[Edit]
And an other thing...a bit off topic. If you want only 26 products set a limit to the collection. Do not load the full collection and the just stop after 26 iterations. Again...big performance issue.

$collection->setPage(1, 26);
//or
$collection-getSelect()->limit(26);
  • Thank you very much for your helpful answer and extra pointers. Please see edited question for the code I ended up using. Would ->addAttributeToSelect('*') create any noticeable performance issues than adding each attribute I need separately? – Sarah Oct 28 '13 at 15:20
  • @Sarah If you add all the attributes you can have a performance issue. I think it's better just to add the ones you need if they are not that many. – Marius Oct 28 '13 at 15:43

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.