How to Update Catalog Product Listing Layout in Magento 1.9.2

layoutlayout-updatemagento-1.9

I have created custom module and update layout for catalog product listing page and product detail page shown below.

<layout version="0.1.0">
<catalog_product_view translate="label">
        <reference name="product.info.addtocart">
            <block type="core/template" name="mytest" template="mytest/mytest.phtml"/>
        </reference>
        <reference name="product.info.additional">
            <block type="core/template" name="mytest"
                   template="mytest/mytest.phtml"/>
        </reference>
    </catalog_product_view>
    <catalog_category_layered translate="label">
        <reference name="product.info.addtocart">
            <block type="core/template" name="mytest" template="mytest/mytest.phtml"/>
        </reference>
        <reference name="product.info.additional">
            <block type="core/template" name="mytest"
                   template="mytest/mytest.phtml"/>
        </reference>
    </catalog_category_layered>
</layout>

Its working fine for product detail page but it won't work on catalog product listing page.

Please advice me how to add custom block under the product price/Add Cart button in product listing page?

Best Answer

This will work well for <catalog_product_view>. The reason is because the child blocks are called out in the phtml files.

For the Catalog Product List you will need to do a bit more.

In 1.9.2 if you open the /template/catalog/product/list.phtml, you will see the below code:

<?php
// Provides extra blocks on which to hang some features for products in the list
// Features providing UI elements targeting this block will display directly below the product name
if ($this->getChild('name.after')) {
   $_nameAfterChildren = $this->getChild('name.after')->getSortedChildren();
   foreach ($_nameAfterChildren as $_nameAfterChildName) {
     $_nameAfterChild = $this->getChild('name.after')->getChild($_nameAfterChildName);
     $_nameAfterChild->setProduct($_product);
     echo $_nameAfterChild->toHtml();
   }
}
?>

Now we will be re-using the above code logic as below:

Inside catalog.xml or local.xml paste the code:

<catalog_category_default translate="label">
    <label>Catalog Category (Non-Anchor)</label>
    <reference name="left_first">
        <block type="catalog/navigation" name="catalog.leftnav" after="currency" template="catalog/navigation/left.phtml">
            <block type="core/text_list" name="catalog.leftnav.state.renderers" as="state_renderers" />
        </block>
    </reference>
    <reference name="content">
        <block type="catalog/category_view" name="category.products" template="catalog/category/view.phtml">
            <block type="catalog/product_list" name="product_list" template="catalog/product/list.phtml">
                <block type="core/text_list" name="product_list.name.after" as="name.after" />
                <block type="core/text_list" name="product_list.price.cart.after" as="price.cart.after">
                    <block type="core/template" name="mytest" template="mytest/mytest.phtml"/>
                </block>
                <block type="core/text_list" name="product_list.after" as="after" />
                <block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
                    <block type="page/html_pager" name="product_list_toolbar_pager"/>
                    <!-- The following code shows how to set your own pager increments -->
                    <!--
                        <action method="setDefaultListPerPage"><limit>4</limit></action>
                        <action method="setDefaultGridPerPage"><limit>9</limit></action>
                        <action method="addPagerLimit"><mode>list</mode><limit>2</limit></action>
                        <action method="addPagerLimit"><mode>list</mode><limit>4</limit></action>
                        <action method="addPagerLimit"><mode>list</mode><limit>6</limit></action>
                        <action method="addPagerLimit"><mode>list</mode><limit>8</limit></action>
                        <action method="addPagerLimit" translate="label"><mode>list</mode><limit>all</limit><label>All</label></action>
                    -->
                </block>
                <action method="addColumnCountLayoutDepend"><layout>empty</layout><count>6</count></action>
                <action method="addColumnCountLayoutDepend"><layout>one_column</layout><count>5</count></action>
                <action method="addColumnCountLayoutDepend"><layout>two_columns_left</layout><count>4</count></action>
                <action method="addColumnCountLayoutDepend"><layout>two_columns_right</layout><count>4</count></action>
                <action method="addColumnCountLayoutDepend"><layout>three_columns</layout><count>3</count></action>
                <action method="setToolbarBlockName"><name>product_list_toolbar</name></action>
                <!-- Since the addColumnCountLayoutDepend does not work, we are manually setting the max columns -->
                <action method="setColumnCount"><count>4</count></action>
            </block>
        </block>
    </reference>
</catalog_category_default>

If you can notice, there is a block called:

<block type="core/text_list" name="product_list.price.cart.after" as="price.cart.after"> <block type="core/template" name="mytest" template="mytest/mytest.phtml"/> </block>

This will help display all your custom blocks in one place. Since you want to display this custom below Price/Add to Cart, search for "GRID MODE" and inside the FOREACH loop the in the file - /template/catalog/product/list.phtml and paste the code below the div:

<?php
// Provides extra blocks on which to hang some features for products in the list
// Features providing UI elements targeting this block will display directly below the product name
if ($this->getChild('price.cart.after')) {
   $_priceCartAfterChildren = $this->getChild('price.cart.after')->getSortedChildren();
   foreach ($_priceCartAfterChildren as $_priceCartAfterChildName) {
     $_priceCartAfterChild = $this->getChild('price.cart.after')->getChild($_priceCartAfterChildName);
     $_priceCartAfterChild->setProduct($_product);
     echo $_priceCartAfterChild->toHtml();
   }
}
?>

So now your list.phtml will look like below:

    <?php
/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE_AFL.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/afl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magento.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    design
 * @package     rwd_default
 * @copyright   Copyright (c) 2006-2015 X.commerce, Inc. (http://www.magento.com)
 * @license     http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
 */
?>
<?php
/**
 * Product list template
 *
 * @see Mage_Catalog_Block_Product_List
 */
/* @var $this Mage_Catalog_Block_Product_List */
?>
<?php
    $_productCollection=$this->getLoadedProductCollection();
    $_helper = $this->helper('catalog/output');
?>
<?php if(!$_productCollection->count()): ?>
<p class="note-msg"><?php echo $this->__('There are no products matching the selection.') ?></p>
<?php else: ?>
<div class="category-products">
    <?php echo $this->getToolbarHtml() ?>
    <?php // List mode ?>
    <?php if($this->getMode()!='grid'): ?>
    <?php $_iterator = 0; ?>
    <ol class="products-list" id="products-list">
    <?php foreach ($_productCollection as $_product): ?>
        <li class="item<?php if( ++$_iterator == sizeof($_productCollection) ): ?> last<?php endif; ?>">
            <?php // Product Image ?>
            <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" class="product-image">
                <?php /* Based on the native RWD styling, product images are displayed at a max of ~400px wide when viewed on a
                        one column page layout with four product columns from a 1280px viewport. For bandwidth reasons,
                        we are going to serve a 300px image, as it will look fine at 400px and most of the times, the image
                        will be displayed at a smaller size (eg, if two column are being used or viewport is smaller than 1280px).
                        This $_imgSize value could even be decreased further, based on the page layout
                        (one column, two column, three column) and number of product columns. */ ?>
                <?php $_imgSize = 300; ?>
                <img id="product-collection-image-<?php echo $_product->getId(); ?>"
                     src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->keepFrame(false)->resize($_imgSize); ?>"
                     alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
            </a>
            <?php // Product description ?>
            <div class="product-shop">
                <div class="f-fix">
                    <div class="product-primary">
                        <?php $_productNameStripped = $this->stripTags($_product->getName(), null, true); ?>
                        <h2 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $_productNameStripped; ?>"><?php echo $_helper->productAttribute($_product, $_product->getName() , 'name'); ?></a></h2>
                        <?php if($_product->getRatingSummary()): ?>
                        <?php echo $this->getReviewsSummaryHtml($_product) ?>
                        <?php endif; ?>
                        <?php
                        // Provides extra blocks on which to hang some features for products in the list
                        // Features providing UI elements targeting this block will display directly below the product name
                        if ($this->getChild('name.after')) {
                            $_nameAfterChildren = $this->getChild('name.after')->getSortedChildren();
                            foreach ($_nameAfterChildren as $_nameAfterChildName) {
                                $_nameAfterChild = $this->getChild('name.after')->getChild($_nameAfterChildName);
                                $_nameAfterChild->setProduct($_product);
                                echo $_nameAfterChild->toHtml();
                            }
                        }
                        ?>
                    </div>
                    <div class="product-secondary">
                        <?php echo $this->getPriceHtml($_product, true) ?>
                    </div>
                    <div class="product-secondary">
                        <?php if(!$_product->canConfigure() && $_product->isSaleable()): ?>
                            <p class="action"><button type="button" title="<?php echo $this->quoteEscape($this->__('Add to Cart')) ?>" class="button btn-cart" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')"><span><span><?php echo $this->__('Add to Cart') ?></span></span></button></p>
                        <?php elseif($_product->getStockItem() && $_product->getStockItem()->getIsInStock()): ?>
                            <p class="action"><a title="<?php echo $this->quoteEscape($this->__('View Details')) ?>" class="button" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->__('View Details') ?></a></p>
                        <?php else: ?>
                            <p class="action availability out-of-stock"><span><?php echo $this->__('Out of stock') ?></span></p>
                        <?php endif; ?>
                        <ul class="add-to-links">
                            <?php if ($this->helper('wishlist')->isAllow()) : ?>
                                <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
                            <?php endif; ?>
                            <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
                                <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
                            <?php endif; ?>
                        </ul>
                    </div>
                    <div class="desc std">
                        <?php echo $_helper->productAttribute($_product, $_product->getShortDescription(), 'short_description') ?>
                        <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $_productNameStripped ?>" class="link-learn"><?php echo $this->__('Learn More') ?></a>
                    </div>
                </div>
            </div>
        </li>
    <?php endforeach; ?>
    </ol>
    <script type="text/javascript">decorateList('products-list', 'none-recursive')</script>

    <?php else: ?>

    <?php // Grid Mode ?>

    <?php $_collectionSize = $_productCollection->count() ?>
    <?php $_columnCount = $this->getColumnCount(); ?>
    <ul class="products-grid products-grid--max-<?php echo $_columnCount; ?>-col">
        <?php $i=0; foreach ($_productCollection as $_product): ?>
            <?php /*if ($i++%$_columnCount==0): ?>
            <?php endif*/ ?>
            <li class="item<?php if(($i-1)%$_columnCount==0): ?> first<?php elseif($i%$_columnCount==0): ?> last<?php endif; ?>">
                <a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" class="product-image">
                    <?php $_imgSize = 210; ?>
                    <img id="product-collection-image-<?php echo $_product->getId(); ?>"
                         src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize($_imgSize); ?>"
                         alt="<?php echo $this->stripTags($this->getImageLabel($_product, 'small_image'), null, true) ?>" />
                </a>
                <div class="product-info">
                    <h2 class="product-name"><a href="<?php echo $_product->getProductUrl() ?>" title="<?php echo $this->stripTags($_product->getName(), null, true) ?>"><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></a></h2>
                    <?php
                    // Provides extra blocks on which to hang some features for products in the list
                    // Features providing UI elements targeting this block will display directly below the product name
                    if ($this->getChild('name.after')) {
                        $_nameAfterChildren = $this->getChild('name.after')->getSortedChildren();
                        foreach ($_nameAfterChildren as $_nameAfterChildName) {
                            $_nameAfterChild = $this->getChild('name.after')->getChild($_nameAfterChildName);
                            $_nameAfterChild->setProduct($_product);
                            echo $_nameAfterChild->toHtml();
                        }
                    }
                    ?>
                    <?php echo $this->getPriceHtml($_product, true) ?>
                    <?php if($_product->getRatingSummary()): ?>
                    <?php echo $this->getReviewsSummaryHtml($_product, 'short') ?>
                    <?php endif; ?>
                    <div class="actions">
                        <?php if(!$_product->canConfigure() && $_product->isSaleable()): ?>
                            <button type="button" title="<?php echo $this->quoteEscape($this->__('Add to Cart')) ?>" class="button btn-cart" onclick="setLocation('<?php echo $this->getAddToCartUrl($_product) ?>')"><span><span><?php echo $this->__('Add to Cart') ?></span></span></button>
                        <?php elseif($_product->getStockItem() && $_product->getStockItem()->getIsInStock()): ?>
                            <a title="<?php echo $this->quoteEscape($this->__('View Details')) ?>" class="button" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->__('View Details') ?></a>
                        <?php else: ?>
                            <p class="availability out-of-stock"><span><?php echo $this->__('Out of stock') ?></span></p>
                        <?php endif; ?>
                        <ul class="add-to-links">
                            <?php if ($this->helper('wishlist')->isAllow()) : ?>
                                <li><a href="<?php echo $this->helper('wishlist')->getAddUrl($_product) ?>" class="link-wishlist"><?php echo $this->__('Add to Wishlist') ?></a></li>
                            <?php endif; ?>
                            <?php if($_compareUrl=$this->getAddToCompareUrl($_product)): ?>
                                <li><span class="separator">|</span> <a href="<?php echo $_compareUrl ?>" class="link-compare"><?php echo $this->__('Add to Compare') ?></a></li>
                            <?php endif; ?>
                        </ul>
                    </div>

                    <?php
                    // Provides extra blocks on which to hang some features for products in the list
                    // Features providing UI elements targeting this block will display directly below the product name
                    if ($this->getChild('price.cart.after')) {
                        $_priceCartAfterChildren = $this->getChild('price.cart.after')->getSortedChildren();
                        foreach ($_priceCartAfterChildren as $_priceCartAfterChildName) {
                            $_priceCartAfterChild = $this->getChild('price.cart.after')->getChild($_priceCartAfterChildName);
                            $_priceCartAfterChild->setProduct($_product);
                            echo $_priceCartAfterChild->toHtml();
                        }
                    }
                    ?>
                </div>
            </li>
            <?php /*if ($i%$_columnCount==0 || $i==$_collectionSize): ?>
            <?php endif*/ ?>
        <?php endforeach ?>
    </ul>
    <script type="text/javascript">decorateGeneric($$('ul.products-grid'), ['odd','even','first','last'])</script>
    <?php endif; ?>

    <div class="toolbar-bottom">
        <?php echo $this->getToolbarHtml() ?>
    </div>
</div>
<?php endif; ?>
<?php
// Provides a block where additional page components may be attached, primarily good for in-page JavaScript
if ($this->getChild('after')) {
    $_afterChildren = $this->getChild('after')->getSortedChildren();
    foreach ($_afterChildren as $_afterChildName) {
        $_afterChild = $this->getChild('after')->getChild($_afterChildName);
        //set product collection on after blocks
        $_afterChild->setProductCollection($_productCollection);
        echo $_afterChild->toHtml();
    }
}
?>

Hope this helps. Let me know if this works for you.

Happy Coding...

Related Topic