Die geschichtete Navigation wird nicht mit Sammlungsattributen gefüllt - CMS-Seite


7

Ich versuche, einer CMS-Seite, die ein Widget enthält, das eine benutzerdefinierte Produktsammlung enthält (Produkte, die "neu" sind), eine geschichtete Navigation hinzuzufügen. In diesem Widget befinden sich Funktionen, die diese Sammlung mit den richtigen Parametern filtern. Wie übergebe ich diese Sammlung an den mehrschichtigen Navigationsblock und lasse deren Attribute angezeigt werden?

So rufe ich die geschichtete Navigation im benutzerdefinierten CMS-Layout-XML auf:

<reference name="content">
        <!-- Layered Navigation Block -->
        <block type="catalog/layer_view" name="catalog.leftnav" before="-" template="catalog/layer/view.phtml" >
        </block>
</reference>

So rufe ich die Produktkollektion auf die CMS-Seite auf:

{{widget type="catalog/product_widget_new" display_type="new_products" show_pager="1" products_count="60" template="catalog/product/widget/new/content/new_grid.phtml"}}

So generiere ich die Produktkollektion im Widgets-Block:

protected function _getProductCollection()
{
    $todayStartOfDayDate = Mage::app()->getLocale()->date()
        ->setTime('00:00:00')
        ->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
    $todayEndOfDayDate = Mage::app()->getLocale()->date()
        ->setTime('23:59:59')
        ->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);
    /** @var $collection Mage_Catalog_Model_Resource_Product_Collection */
    $collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect('*')->setVisibility(Mage::getSingleton('catalog/product_visibility')->getVisibleInCatalogIds());
    $this->_addProductAttributesAndPrices($collection)
        ->addStoreFilter()
        ->addAttributeToFilter('news_from_date', array('or' => array(
            0 => array('date' => true, 'to' => $todayEndOfDayDate),
            1 => array('is' => new Zend_Db_Expr('null')))
        ), 'left')
        ->addAttributeToFilter('news_to_date', array('or' => array(
            0 => array('date' => true, 'from' => $todayStartOfDayDate),
            1 => array('is' => new Zend_Db_Expr('null')))
        ), 'left')
        ->addAttributeToFilter(
            array(
                array('attribute' => 'news_from_date', 'is' => new Zend_Db_Expr('not null')),
                array('attribute' => 'news_to_date', 'is' => new Zend_Db_Expr('not null'))
            )
        )
        ->setPageSize($this->getProductsCount())
        ->setCurPage(1);
    return $collection;
}

Die Vorlagenseite des Widgets ist eine Standardmethode zum Anzeigen von Preisen, Bewertungen, Bildern usw. in einem variablen Seitenformat.


1
Was Sie erreichen möchten, ist nicht möglich, da jetzt zumindest CMS-Seiten und Widgets sowie Layout-Updates verwendet werden. Hier ist warum. Magento hat 2-Schicht-Modelle. Eine funktioniert, wenn Sie sich im Kontext einer Kategorie befinden, und eine funktioniert, wenn Sie sich im Kontext der Suchergebnisse befinden. Ihr Beispiel fällt nicht in eine dieser Kategorien. Sie benötigen ein benutzerdefiniertes Ebenenmodell, das Ihren Sammlungstyp (neue Produkte) verarbeitet.
Marius

1
Möglicherweise kann ich eine Lösung finden, aber dazu muss ein benutzerdefiniertes Modul mit einem benutzerdefinierten Controller-, Block- und Layer-Modell (und möglicherweise anderen) geschrieben werden. Aber bevor ich nach einer Lösung suche, möchte ich wissen, ob dies für Sie funktioniert. Ich meine, Sie werden immer noch eine URL haben können, www.mysite.com/new-productsaber dies new-productswird keine CMS-Seite sein. Es wird von einem separaten Controller verwaltet. Und es wird alle neuen Produkte enthalten, paginiert (vielleicht mit Sortieroptionen, wenn ich herausfinde, wie). Geht das für dich? oder möchten Sie eine einfache CMS-Seitenlösung?
Marius

@Marius das wäre eine vernünftige Lösung. Ich nehme an, ich kann diese Lösung genauso einfügen wie ein Widget auf einer CMS-Seite, oder?
easymoden00b

1
Nicht wirklich. Die Lösung, an die ich denke, wird eine separate Seite mit einem separaten Controller erstellen (einige Vorlagendateien möglicherweise). das kann nicht wie eine csm-seite geändert werden. Es wird einfach da sein und funktionieren :) Das war's. Es geht darum, ein neues Modul zu erstellen
Marius

@ Marius Ich sehe, das kann auch funktionieren.
easymoden00b

Antworten:


7

Die geschichtete Navigation benötigt eine aktive Kategorie, um zu funktionieren. Fügen Sie den folgenden Block zu Ihrer layout-xml auf Ihren cms-Seiten hinzu.

<cms_page>
    <block type="catalog/layer_view" name="catalog.leftnav" before="-" template="catalog/layer/view.phtml">
        <action method="setCategoryId"><category_id>2</category_id></action>
    </block>
</cms_page>

1
Womit füllen Sie Ihre Produkte noch?
Roman204

1
Ja, ich verstehe, in diesem Fall müssen Sie den Mage_Catalog_Model__Layer: getProductCollection überschreiben ... Ich werde sehen, was ich hier tun kann, um eine Lösung bereitzustellen.
Roman204

2
@ easymoden00b Versuchen Sie, die ID der Stammkategorie hinzuzufügen. Und stellen Sie sicher, dass Sie für diese Kategorie "Ist Anker" auf "Ja" gesetzt haben.
MagePsycho

1
@MagePsycho dann werden die filterbaren Attribute aller Produkte zum Filtern verfügbar sein, da ich die Frage verstehe, dass der Filter nur die Produkte aus dem Widget enthalten sollte, bitte korrigieren Sie mich, wenn ich falsch
liege

1
AFAIK, OP will globale Liste neuer Produkte mit geschichteter Navigation.
MagePsycho

28

Wie in den Kommentaren erläutert, gibt es meines Erachtens keine Möglichkeit, dies mithilfe der CMS-Seiten zu tun, da der Liste der neuen Produkte kein Ebenenmodell zugeordnet ist. Sie haben nur Ebenenmodelle für den Kategoriekontext und den Suchkontext.
Meine Lösung (getestet und funktioniert) besteht darin, ein Modul zu schreiben, das alle auf einer Seite als neu gekennzeichneten Produkte auflistet und über ein Ebenenmodell verfügt, das die Sammlung neuer Produkte verwaltet.
Hier geht. Seien Sie vorbereitet, es ist lang.
Ich habe die Nebenstelle angerufen, kann StackExchange_NewProductsaber den Namen jederzeit ändern.
Sie benötigen folgende Dateien:

app/etc/modules/StackExchange_NewProducts.xml - die Deklarationsdatei:

<?xml version="1.0"?>
<config>
    <modules>
        <StackExchange_NewProducts>
            <codePool>local</codePool>
            <active>true</active>
            <depends>
                <Mage_Catalog />
            </depends>
        </StackExchange_NewProducts>
    </modules>
</config>

app/code/local/StackExchange/NewProducts/etc/config.xml - die Konfigurationsdatei

<?xml version="1.0"?>
<config>
    <modules>
        <StackExchange_NewProducts>
            <version>1.0.0</version>
        </StackExchange_NewProducts>
    </modules>
    <global>
        <models>
            <stackexchange_newproducts>
                <class>StackExchange_NewProducts_Model</class>
            </stackexchange_newproducts>
        </models>
        <blocks>
            <stackexchange_newproducts>
                <class>StackExchange_NewProducts_Block</class>
            </stackexchange_newproducts>
        </blocks>
        <helpers>
            <stackexchange_newproducts>
                <class>StackExchange_NewProducts_Helper</class>
            </stackexchange_newproducts>
        </helpers>
        <events>
            <controller_front_init_routers> <!-- create a custom router to handle the 'new-products' url -->
                <observers>
                    <stackexchange_newproducts>
                        <class>StackExchange_NewProducts_Controller_Router</class>
                        <method>initControllerRouters</method>
                    </stackexchange_newproducts>
                </observers>
            </controller_front_init_routers>
        </events>
    </global>
    <frontend>
        <routers> <!-- declare a router -->
            <newproducts>
                <use>standard</use>
                <args>
                    <module>StackExchange_NewProducts</module>
                    <frontName>newproducts</frontName>
                </args>
            </newproducts>
        </routers>
        <layout>
            <updates>
                <stackexchange_newproducts>
                    <file>stackexchange_newproducts.xml</file>
                </stackexchange_newproducts>
            </updates>
        </layout>
    </frontend>
</config>

app/code/local/StackExchange/NewProducts/Controller/Router.php- Der benutzerdefinierte Router, der die URL verarbeitet new-productsund sie einem Controller und einer Aktion zuordnet

<?php
class StackExchange_NewProducts_Controller_Router extends Mage_Core_Controller_Varien_Router_Abstract
{
    const NEW_PRODUCTS_URL_KEY = 'new-products';
    public function initControllerRouters($observer)
    {
        $front = $observer->getEvent()->getFront();
        $front->addRouter('stackexchange_newproducts', $this);
        return $this;
    }

    public function match(Zend_Controller_Request_Http $request)
    {
        if (!Mage::isInstalled()) {
            Mage::app()->getFrontController()->getResponse()
                ->setRedirect(Mage::getUrl('install'))
                ->sendResponse();
            exit;
        }
        $urlKey = trim($request->getPathInfo(), '/');
        if ($urlKey == self::NEW_PRODUCTS_URL_KEY) {
            $request->setModuleName('newproducts')
                ->setControllerName('index')
                ->setActionName('index');
            $request->setAlias(
                Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,
                $urlKey
            );
            return true;
        }
        return false;
    }
}

app/code/local/StackExchange/NewProducts/controllers/IndexController.php - die tatsächliche Steuerung, die die neuen Produkte anzeigt

<?php
class StackExchange_NewProducts_IndexController extends Mage_Core_Controller_Front_Action
{
    public function indexAction()
    {
        $this->loadLayout();
        $this->renderLayout();
    }
}

app/code/local/StackExchange/NewProducts/Helper/Data.php - der allgemeine Helfer des Moduls

<?php
class StackExchange_NewProducts_Helper_Data extends Mage_Core_Helper_Abstract
{

}

app/design/frontend/base/default/layout/stackexchange_newproducts.xml - die Modullayoutdatei, die den Inhalt der Seite definiert

<?xml version="1.0"?>
<layout>
    <newproducts_index_index>
        <reference name="root">
            <action method="setTemplate">
                <template>page/2columns-left.phtml</template>
            </action>
        </reference>
        <reference name="left">
            <block type="stackexchange_newproducts/layer_new" name="catalog.leftnav" before="-" template="catalog/layer/view.phtml" />
        </reference>
        <reference name="content">
            <block type="core/template" name="new_products_container" as="new_products_container" template="stackexchange_newproducts/container.phtml">
                <action method="setTitle" translate="title" module="stackexchange_newproducts">
                    <title>New Products</title>
                </action>
                <block type="stackexchange_newproducts/new" name="new_product" as="new_products" template="catalog/product/list.phtml">
                    <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"/>
                    </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>
                </block>
            </block>
        </reference>

    </newproducts_index_index>
</layout>

app/code/local/StackExchange/NewProducts/Block/New.php - der Block, der die neue Produktkollektion rendern soll:

<?php
class StackExchange_NewProducts_Block_New extends Mage_Catalog_Block_Product_List
{
    public function __construct()
    {
        parent::__construct();
    }
    public function getModuleName()
    {
        return 'Mage_Catalog';
    }
    protected function _getProductCollection()
    {
        if (is_null($this->_productCollection)) {
            $this->_productCollection = $this->getLayer()->getProductCollection();
        }
        return $this->_productCollection;
    }
    public function getLayer()
    {
        $layer = Mage::registry('current_layer');
        if ($layer) {
            return $layer;
        }
        return Mage::getSingleton('stackexchange_newproducts/layer');
    }
}

app/code/local/StackExchange/NewProducts/Block/Layer/New.php - der Ebenenblock, der auf der linken Seite angezeigt werden soll (Filter)

<?php
class StackExchange_NewProducts_Block_Layer_New extends Mage_Catalog_Block_Layer_View
{
    public function getLayer()
    {
        if (!$this->hasData('_layer')){
            $layer = Mage::getSingleton('stackexchange_newproducts/layer');
            $this->setData('_layer', $layer);
        }
        return $this->getData('_layer');
    }
    protected function _initBlocks()
    {
        parent::_initBlocks();
        $this->_attributeFilterBlockName    = 'stackexchange_newproducts/layer_filter_attribute';
        $this->_priceFilterBlockName        = 'stackexchange_newproducts/layer_filter_price';
        $this->_decimalFilterBlockName      = 'stackexchange_newproducts/layer_filter_decimal';
    }
    protected function _prepareLayout()
    {
        $stateBlock = $this->getLayout()->createBlock($this->_stateBlockName)
            ->setLayer($this->getLayer());
        $this->setChild('layer_state', $stateBlock);

        $filterableAttributes = $this->_getFilterableAttributes();
        foreach ($filterableAttributes as $attribute) {
            if ($attribute->getAttributeCode() == 'price') {
                $filterBlockName = $this->_priceFilterBlockName;
            } elseif ($attribute->getBackendType() == 'decimal') {
                $filterBlockName = $this->_decimalFilterBlockName;
            } else {
                $filterBlockName = $this->_attributeFilterBlockName;
            }

            $this->setChild($attribute->getAttributeCode() . '_filter',
                $this->getLayout()->createBlock($filterBlockName)
                    ->setLayer($this->getLayer())
                    ->setAttributeModel($attribute)
                    ->init());
        }

        $this->getLayer()->apply();
        return $this;
    }
}

Jetzt benötigt jeder Attributtyp einen Filterblock:

app/code/local/StackExchange/NewProducts/Block/Layer/Filter/Attribute.php - allgemeiner Filterblock für Attribute

<?php 
class StackExchange_NewProducts_Block_Layer_Filter_Attribute extends Mage_Catalog_Block_Layer_Filter_Attribute
{
    public function __construct()
    {
        parent::__construct();
        $this->_filterModelName = 'stackexchange_newproducts/layer_filter_attribute';
    }
}

app/code/local/StackExchange/NewProducts/Block/Layer/Filter/Decimal.php - Filterblock für Dezimalattribute

<?php 
class StackExchange_NewProducts_Block_Layer_Filter_Decimal extends Mage_Catalog_Block_Layer_Filter_Decimal
{
    public function __construct()
    {
        parent::__construct();
        $this->_filterModelName = 'stackexchange_newproducts/layer_filter_decimal';
    }
}

app/code/local/StackExchange/NewProducts/Block/Layer/Filter/Price.php - Filterblock für Preisattribut

<?php 
class StackExchange_NewProducts_Block_Layer_Filter_Price extends Mage_Catalog_Block_Layer_Filter_Price
{
    public function __construct()
    {
        parent::__construct();
        $this->_filterModelName = 'stackexchange_newproducts/layer_filter_price';
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer.php - das Schichtmodell für den Umgang mit neuen Produkten

<?php
class StackExchange_NewProducts_Model_Layer extends Mage_Catalog_Model_Layer
{
    public function getStateKey()
    {
        if ($this->_stateKey === null) {
            $this->_stateKey = 'STORE_'.Mage::app()->getStore()->getId()
                . '_NEW_PRODUCTS_'
                . '_CUSTGROUP_' . Mage::getSingleton('customer/session')->getCustomerGroupId();
        }

        return $this->_stateKey;
    }

    public function getStateTags(array $additionalTags = array())
    {
        $additionalTags = array_merge($additionalTags, array('new_products'));
        return $additionalTags;
    }

    public function getProductCollection()
    {
        if (isset($this->_productCollections['new_products'])) {
            $collection = $this->_productCollections['new_products'];
        } else {
            $collection = $this->_getCollection();
            $this->prepareProductCollection($collection);
            $this->_productCollections['new_products'] = $collection;
        }

        return $collection;
    }
    public function prepareProductCollection($collection)
    {
        $collection
            ->addAttributeToSelect(Mage::getSingleton('catalog/config')->getProductAttributes())
            ->addMinimalPrice()
            ->addFinalPrice()
            ->addTaxPercents()
            ->addUrlRewrite();

        Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
        Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
        return $this;
    }

    protected function _getCollection()
    {
        $todayStartOfDayDate  = Mage::app()->getLocale()->date()
            ->setTime('00:00:00')
            ->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);

        $todayEndOfDayDate  = Mage::app()->getLocale()->date()
            ->setTime('23:59:59')
            ->toString(Varien_Date::DATETIME_INTERNAL_FORMAT);

        $collection = Mage::getModel('catalog/product')->getCollection()
            ->addStoreFilter()
            ->addAttributeToFilter('news_from_date', array('or'=> array(
                0 => array('date' => true, 'to' => $todayEndOfDayDate),
                1 => array('is' => new Zend_Db_Expr('null')))
            ), 'left')
            ->addAttributeToFilter('news_to_date', array('or'=> array(
                0 => array('date' => true, 'from' => $todayStartOfDayDate),
                1 => array('is' => new Zend_Db_Expr('null')))
            ), 'left')
            ->addAttributeToFilter(
                array(
                    array('attribute' => 'news_from_date', 'is'=>new Zend_Db_Expr('not null')),
                    array('attribute' => 'news_to_date', 'is'=>new Zend_Db_Expr('not null'))
                )
            )
            ->addAttributeToSort('news_from_date', 'desc');
        return $collection;
    }
}

Wie jedes Attribut einen Block für Filter benötigt, benötigt es auch ein Modell für die Behandlung von Filtern:

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Attribute.php - das allgemeine Attributfiltermodell

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Attribute extends Mage_Catalog_Model_Layer_Filter_Attribute
{
    protected function _createItem($label, $value, $count = 0)
    {
        return Mage::getModel('stackexchange_newproducts/layer_filter_item')
            ->setFilter($this)
            ->setLabel($label)
            ->setValue($value)
            ->setCount($count);
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Decimal.php - das Filtermodell für Dezimalattribute

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Decimal extends Mage_Catalog_Model_Layer_Filter_Attribute
{
    protected function _createItem($label, $value, $count = 0)
    {
        return Mage::getModel('stackexchange_newproducts/layer_filter_item')
            ->setFilter($this)
            ->setLabel($label)
            ->setValue($value)
            ->setCount($count);
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Price.php - das Preisattributfiltermodell

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Price extends Mage_Catalog_Model_Layer_Filter_Price
{
    protected function _createItem($label, $value, $count = 0)
    {
        return Mage::getModel('stackexchange_newproducts/layer_filter_item')
            ->setFilter($this)
            ->setLabel($label)
            ->setValue($value)
            ->setCount($count);
    }
}

app/code/local/StackExchange/NewProducts/Model/Layer/Filter/Item.php- Die Filter erfordern eine Sammlung von Objektobjekten. Dies ist das Objekt Objekt - nicht sicher, ob dies benötigt wird. Ich denke, dass das Standard-Katalogelementmodell verwendet werden kann.

<?php 
class StackExchange_NewProducts_Model_Layer_Filter_Item extends Mage_Catalog_Model_Layer_Filter_Item
{

}

app/design/frontend/base/default/template/stackexchange_newproducts/container.phtml - Eine Vorlagendatei, die als Container für die neuen Produkte fungiert, sodass Sie einen Titel festlegen und Sitzungsnachrichten anzeigen können.

<?php if ($this->getTitle()) : ?>
    <div class="page-title category-title">
        <h1><?php echo $this->getTitle() ?></h1>
    </div>
<?php endif;?>
<?php echo $this->getMessagesBlock()->getGroupedHtml() ?>
<?php echo $this->getChildHtml();?>

Das ist es. Leeren Sie den Cache, nachdem Sie alle Dateien erstellt und die Kompilierung deaktiviert haben.
Hier ist ein Screenshot, wie es auf meiner Seite aussieht
Bildschirmfoto. (unter Verwendung von ce 1.7 mit Beispieldaten)


4
Es fehlt nur noch die Übersetzungsdatei.
Marius

1
gute Modulbenennung dort :)
David Manners

3
@ DavidManners. Ja. Ich weiß nicht, woher der Name kommt, aber er hat mich einfach getroffen :). Ich hoffe, Sie verlangen keine Urheberrechtsentschädigung.
Marius

3
ein Bier reicht;)
David Manners

2
Vorsitzender @Marius - + 1votw
Amit Bera
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.