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>
Это просто упрощенная версия шаблона списка товаров Magento: catalog/product/list.phtml
РАБОЧАЯ
При встраивании блока на странице CMS он отлично работает. Пример:
{{block type="catalog/product_list" category_id="13" template="custom/featured-product.phtml" }}
НЕ РАБОТАЕТ
При встраивании блока через 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>
Для полноты я явно выделяю блок в page/html/footer.phtml
следующим образом:
<?php echo $this->getChildHtml('product_of_the_month') ?>
Любые идеи?
Мое лучшее предположение: мой local.xml
неверен. Есть ли родительский блок, который мне нужно загрузить?
[Обновления]
Мой исходный код приводит к сбою страницы продукта. Обходной путь не основывает код так сильно на основном файле Magento: catalog/product/list.phtml
. В частности, избегая этой строки:
<?php $_productCollection = $this->getLoadedProductCollection() ?>
[Решение]
Здесь приведена рабочая версия с примерами для использования в CMS Pages и LayoutXML:
qaru.site/info/440194/...
Ответы
Ответ 1
Нашел рабочее решение, используя совет Алана Шторма.
/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>
Короче говоря, коллекция создается вручную, а не получает коллекцию (по моей первоначальной попытке):
<?php $_productCollection = $this->getLoadedProductCollection() ?>
<?php $_collectionSize = $_productCollection->count(); ?>
Использование на странице CMS:
{{block type="core/template" category_id="13" label="Product of the Month" template="custom/featured-product.phtml" }}
Использование в шаблоне:
/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>
/template/page/html/footer.phtml
<?php echo $this->getChildHtml('featured_product') ?>
Полезные ресурсы:
Как получить коллекцию продуктов:
Использование магических геттеров/сеттеров:
Ответ 2
Во-первых, у меня были случайные проблемы на протяжении многих лет, используя узлы атрибутов макета обновления 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>
или
<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>
может помочь и будет моим первым шагом.
После этого я бы посмотрел блок-код, загружающий коллекцию
#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;
}
}
Метод getLoadedProductCollection
завершает вызов _getProductCollection
, а _getProductCollection
- это место, где коллекция фактически загружена.
Итак, некоторый временный код отладки в
protected function _getProductCollection()
{
var_dump(__METHOD__);
var_dump($this->getCategoryId());
Mage::Log(__METHOD__);
Mage::Log($this->getCategoryId());
}
Может помочь убедиться, что ваш идентификатор категории делает его из XML-макета обновления в блок.
Однако, если вы посмотрите немного глубже на _getProductCollection
, вы заметите, что существует несколько условий, при которых сбрасывает идентификатор категории.
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()));
}
}
...
В какой-то другой части кода Magento установлено свойство show_root_category
, или вы находитесь на странице, где есть объект продукта в реестре, Magento переопределит ваш идентификатор категории.
Сложнее сделать вещи, как только коллекция будет загружена, она будет установлена на защищенное свойство
$this->_productCollection = $layer->getProductCollection();
который не имеет общедоступного метода getter.
Способы продолжения здесь - мириады. Если бы это был я, я бы рассмотрел один из следующих
-
Используя специальный класс блоков, который расширяет Mage_Catalog_Block_Product_List
и имеет метод сброса категории в коллекции или загрузки новой коллекции
-
Загрузка коллекции сама, не полагаясь на код в product/list
Ответ 3
Я успешно воссоздал проблему в Magento CE 1.7.0.2.
Сначала я создал 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>
Я выяснил, что некоторые элементы XML обертывания отсутствуют и добавлены некоторые дополнительные строки:
<?xml version="1.0"?>
<layout>
<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>
</layout>
После добавления необходимых элементов XML он работал.