Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento: How to retrieve the minimal price of (i.e.) grouped products?

Tags:

magento

I am trying to display a grouped product's price on the product view page in Magento 1.7.0.2, just as it is being displayed in the category product listing ("Starting at: xx.xx"). I thought I could just use

$this->getPriceHtml($_product, true);

to do so because it works the same way in the category product listing, but as everything I tried to do in Magento, it is not that easy because that method doesnt return anything on the product view page.

I looked a little deeper into Magento's code and figured out that the cause of this problem is the product's minimal price data not being set on the product view page ($_product->getMinimalPrice() returns null).

Therefore I did some research on how to load a product's minimal price which brought up ideas like

$_product->getPriceModel()->getMinimalPrice($_product);

which doesnt work because apparently that method was deprecated and removed in one of the last updates or

$priceModel = Mage::getResourceModel('catalogindex/price');
$priceModel->setStoreId(Mage::app()->getStore()->getId());
$priceModel->setCustomerGroupId(Mage::getSingleton('customer/session')->getCustomerGroupId());

$minimalPrices = $priceModel->getMinimalPrices(array($_product->getId()));
$minimalPrice = $minimalPrices[0];
$_product->setData('minimal_price', $minimalPrice['value']);
$_product->setData('minimal_tax_class_id', $minimalPrice['tax_class_id']);

which doesnt work either because the table 'catalogindex_minimal_price' is empty.

So my question is, how does Magento load the minimal price in the category product listing?

like image 291
Subsurf Avatar asked Aug 21 '12 11:08

Subsurf


2 Answers

I looked a little deeper into Magento's code and tracked down how Magento loads the products of the product list. When viewing the product list, the product collection is loaded by the model Mage_Catalog_Model_Layer, which adds the minimal price and other stuff to the products in the collection by adding joins to the collection’s SQL, but I have not yet found a model that does the same thing for single products instead of collections.

Because I don’t want to use a direct SQL query, I checked out the CatalogIndex module, but that module seems not to be working at all because all its indexing tables are empty or even corrupted.

$data_grouped = Mage::getModel("catalogindex/data_grouped");
$minimal = $data_grouped->getMinimalPrice(array($_product->getId()), Mage::app()->getStore());

looked good at first but it gives me the following error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'catalog_product_index_price.value' in 'field list'

The CatalogIndex module is either deprecated or I’m just too stupid to enable it.

However, I have now created a workaround in my price.phtml template, which uses the same method to retrieve the minimal price and tax percents as the product list does: At the beginning of the template I added the following:

$this->setProduct(
    Mage::getModel("catalog/product")->getCollection()
        ->addAttributeToSelect(Mage::getSingleton("catalog/config")->getProductAttributes())
        ->addAttributeToFilter("entity_id", $this->getProduct()->getId())
        ->setPage(1, 1)
        ->addMinimalPrice()
        ->addFinalPrice()
        ->addTaxPercents()
        ->load()
        ->getFirstItem()
);

which may not be the perfect solution, but it does the job and it does it a little cleaner than iterating over all child products and finding the minimal price that way.

like image 50
Subsurf Avatar answered Nov 15 '22 07:11

Subsurf


This isn't an answer as much as a big HTML comment on Subsurf's answer. If you're reading this, you might be implementing your own custom module to display a product list. In my case, it's a single page just for wholesalers. My goal was to get a list of my own company's products and give them a list like it was another category. I copied my template's list.phtml to my new content.phtml. But getMinimalPrice() was returning NULL, meaning that when this code calls the getPriceHtml(), price.phtml wasn't showing wholesale pricing.

I did a simple module with index controller and a content.phtml. Using the boilerplate I see all over the net, in the indexController.php file, change:

$block = $this->getLayout()->createBlock(
    'Mage_Core_Block_Template',
    'b2b',
    array('template' => 'b2b/content.phtml')
);

to:

$block = $this->getLayout()->createBlock(
    'Mage_Catalog_Block_Product_List',
    'b2b',
    array('template' => 'b2b/content.phtml')
);

This does a lot of the heavy lifting for you to show the products list correctly.


Now, on to the template file, in my case content.phtml, you get your product collection and then use Subsurf's code in the top of the foreach() which repeats.

    $_productCollection = Mage::getModel('catalog/product')
        ->getCollection()
//          ->addAttributeToSelect('*')
// doesn't work     ->addAttributeToSelect('special_price')
        ->addAttributeToSelect('sku')
        ->addAttributeToFilter('status', 1)
        ->addAttributeToFilter('visibility', 4)
        // http://stackoverflow.com/questions/1332742/magento-retrieve-products-with-a-specific-attribute-value
        ->addFieldToFilter( array(
                array('attribute'=>'manufacturer','eq'=>'143')
                , array('attribute'=>'manufacturer','eq'=>'139')
            ))
        ;

echo "<p>There are ".count($_productCollection)." products: </p>";
echo '<div class="category-products">';
// List mode 
if($this->getMode()!='grid') { 
    $_iterator = 0;
    echo'<ol class="products-list" id="products-list">';
    foreach ($_productCollection as $_product) {
        ?>          <li class="item<?php if( ++$_iterator == sizeof($_productCollection) ): ?> last<?php endif; ?>">
        <?php 
        $_product=Mage::getModel("catalog/product")->getCollection()
            ->addAttributeToSelect(Mage::getSingleton("catalog/config")->getProductAttributes())
            ->addAttributeToFilter("entity_id", $_product->getId())
            ->setPage(1, 1)
            ->addMinimalPrice()
            ->addFinalPrice()
            ->addTaxPercents()
            ->load()
            ->getFirstItem()
            );
        echo "Minimal price: ".$_product->getMinimalPrice()."<br>\n";       

Since this isn't a single product's page and I'm using other template code, $this->setProduct() didn't do anything for me. I guessed if there was a set, there might be a get, so $_product=$this->getProduct() was the magic my template's price.phtml needed to work properly. Then I noticed I could just assign the Mage:: in setProduct() directly to $_product.

Thanks, Subsurf!!!

like image 43
Krista K Avatar answered Nov 15 '22 08:11

Krista K