Magento:显示页脚中特定类别的产品

Bre*_*ski 12 magento

我正在为页脚构建一个"月度产品"块.它应该加载类别的产品并显示第一个.

这是我的模板文件custom/featured-product.phtml:

<?php $_productCollection = $this->getLoadedProductCollection() ?>

<div class="featured-product">
    <h2><?php echo $this->__('Product of the Month') ?></h2>

    <?php foreach ($_productCollection as $_product): ?>
        <div class="item">
            <a class="product-image" href="<?php echo $_product->getProductUrl() ?>">
                <img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(200); ?>" alt="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" />
            </a>

            <a class="product-name" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->htmlEscape($_product->getName()) ?></a>

            <?php echo $this->getPriceHtml($_product, true) ?>
        </div>

        <?php
        // Note: Exit after first product.
        break;
        ?>
    <?php endforeach ?>
</div>
Run Code Online (Sandbox Code Playgroud)

它只是Magento产品列表模板的简化版本: catalog/product/list.phtml


工作

将块嵌入CMS页面时,它可以正常工作.例:

{{block type="catalog/product_list" category_id="13" template="custom/featured-product.phtml" }}
Run Code Online (Sandbox Code Playgroud)


不工作

嵌入块时local.xml,它会失败.返回正确的标记但未加载指定的类别.而是加载一组随机(我不选择它们如何选择)产品组.

我的代码在local.xml:

<default>
    <reference name="footer">
        <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" category_id="13" template="custom/featured-product.phtml" />
    </reference>
</default>
Run Code Online (Sandbox Code Playgroud)

为了完整性,我page/html/footer.phtml正如这样明确地渲染块:

<?php echo $this->getChildHtml('product_of_the_month') ?>
Run Code Online (Sandbox Code Playgroud)


有任何想法吗?

我最好的猜测是我local.xml的错误.我需要加载父块吗?


[更新]

我的原始代码崩溃了产品页面.解决方法不是将代码严重依赖于Magento核心文件:catalog/product/list.phtml.特别避免这一行:

<?php $_productCollection = $this->getLoadedProductCollection() ?>
Run Code Online (Sandbox Code Playgroud)


[解]

这里包含一个工作版本,其中包含用于CMS Pages和LayoutXML的示例:https://stackoverflow.com/a/12288000/1497746

Bre*_*ski 12

使用Alan Storm的建议找到了一个可行的解决方案.

/template/custom/featured-product.phtml

<?php
$_categoryId = $this->getCategoryId();

$_productCollection = Mage::getModel('catalog/category')->load($_categoryId)
    ->getProductCollection()
    ->addAttributeToSelect('*')
    ->addAttributeToFilter('status', 1)
    ->addAttributeToFilter('visibility', 4)
    ->setOrder('price', 'ASC');
?>

<div class="featured-product">
    <h2><?php echo $this->__( $this->getLabel() ); ?></h2>

    <?php foreach ($_productCollection as $_product): ?>
        <div class="item">
            <a class="product-image" href="<?php echo $_product->getProductUrl() ?>">
                <img src="<?php echo $this->helper('catalog/image')->init($_product, 'small_image')->resize(200); ?>" alt="<?php echo $this->htmlEscape($this->getImageLabel($_product, 'small_image')) ?>" />
            </a>

            <a class="product-name" href="<?php echo $_product->getProductUrl() ?>"><?php echo $this->htmlEscape($_product->getName()) ?></a>

            <?php echo $this->getPriceHtml($_product, true) ?>
        </div>

        <?php
        // Note: Exit after first product.
        break;
        ?>
    <?php endforeach ?>
</div>
Run Code Online (Sandbox Code Playgroud)

简而言之,集合是手动生成的,而不是接收集合(正如我最初的尝试所做的那样):

<?php $_productCollection = $this->getLoadedProductCollection() ?>
<?php $_collectionSize = $_productCollection->count(); ?>
Run Code Online (Sandbox Code Playgroud)


在CMS页面中使用:

{{block type="core/template" category_id="13" label="Product of the Month" template="custom/featured-product.phtml" }}
Run Code Online (Sandbox Code Playgroud)


在模板中使用:

/layout/local.xml

<default>
    <reference name="footer">
        <block type="core/template" name="custom.featuredProduct" as="featured_product" template="custom/featured-product.phtml">
            <action method="setData"><key>category_id</key><value>13</value></action>
            <action method="setData"><key>label</key><value>Product of the Month</value></action>
        </block>
    </reference>
</default>
Run Code Online (Sandbox Code Playgroud)

/template/page/html/footer.phtml

<?php echo $this->getChildHtml('featured_product') ?>
Run Code Online (Sandbox Code Playgroud)


有用的资源:

如何获得产品系列:

使用魔法getter/setter:


Ala*_*orm 5

首先,我已经使用布局更新XML属性节点设置块值(除多年来随机问题template,as,name,type,或class,所以尝试这样的事情

<default>
    <reference name="footer">
        <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" template="custom/featured-product.phtml">
            <action method="setCategoryId"><id>13</id></action>
        </block>
    </reference>
</default>
Run Code Online (Sandbox Code Playgroud)

或这个

<default>
    <reference name="footer">
        <block type="catalog/product_list" name="custom.featuredProduct" as="product_of_the_month" template="custom/featured-product.phtml">
            <action method="setData"><key>category_id</key><value>13</value></action>
        </block>
    </reference>
</default>
Run Code Online (Sandbox Code Playgroud)

可能会有所帮助,这将是我迈出的第一步.

之后,我会去看一下加载集合的块代码

#File: app/code/core/Mage/Catalog/Block/Product/List.php
class Mage_Catalog_Block_Product_List extends Mage_Catalog_Block_Product_Abstract
{
    ...
    public function getLoadedProductCollection()
    {
        return $this->_getProductCollection();
    }        
    ...
    protected function _getProductCollection()
    {
        if (is_null($this->_productCollection)) {
            $layer = $this->getLayer();
            /* @var $layer Mage_Catalog_Model_Layer */
            if ($this->getShowRootCategory()) {
                $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
            }

            // if this is a product view page
            if (Mage::registry('product')) {
                // get collection of categories this product is associated with
                $categories = Mage::registry('product')->getCategoryCollection()
                    ->setPage(1, 1)
                    ->load();
                // if the product is associated with any category
                if ($categories->count()) {
                    // show products from this category
                    $this->setCategoryId(current($categories->getIterator()));
                }
            }

            $origCategory = null;
            if ($this->getCategoryId()) {
                $category = Mage::getModel('catalog/category')->load($this->getCategoryId());
                if ($category->getId()) {
                    $origCategory = $layer->getCurrentCategory();
                    $layer->setCurrentCategory($category);
                }
            }
            $this->_productCollection = $layer->getProductCollection();

            $this->prepareSortableFieldsByCategory($layer->getCurrentCategory());

            if ($origCategory) {
                $layer->setCurrentCategory($origCategory);
            }
        }

        return $this->_productCollection;
    }                
}
Run Code Online (Sandbox Code Playgroud)

getLoadedProductCollection方法包含一个调用_getProductCollection,并且_getProductCollection是实际加载集合的地方.

所以,一些临时调试代码

protected function _getProductCollection()
{
    var_dump(__METHOD__);
    var_dump($this->getCategoryId());
    Mage::Log(__METHOD__);
    Mage::Log($this->getCategoryId());
}
Run Code Online (Sandbox Code Playgroud)

可以帮助确保您的类别ID从布局更新XML到块.

但是,如果你看得更深一些_getProductCollection,你会注意到它有一些重置类别ID的条件.

if ($this->getShowRootCategory()) {
    $this->setCategoryId(Mage::app()->getStore()->getRootCategoryId());
}
...
if (Mage::registry('product')) {
    // get collection of categories this product is associated with
    $categories = Mage::registry('product')->getCategoryCollection()
        ->setPage(1, 1)
        ->load();
    // if the product is associated with any category
    if ($categories->count()) {
        // show products from this category
        $this->setCategoryId(current($categories->getIterator()));
    }
}
...
Run Code Online (Sandbox Code Playgroud)

是否有其他一些Magento代码设置了show_root_category属性,或者您在注册表中有产品对象的页面上,Magento将覆盖您的类别ID.

使事情变得更加复杂,一旦集合被加载,它就被设置在受保护的属性上

$this->_productCollection = $layer->getProductCollection();
Run Code Online (Sandbox Code Playgroud)

没有公共getter方法.

在这里进行的方式是无数的.如果是我,我会考虑以下之一

  1. 使用扩展的自定义块类,Mage_Catalog_Block_Product_List并具有重置集合上的类别或加载新集合的方法

  2. 自己加载集合,而不依赖于代码 product/list