Frage

Ich möchte auf der Kategorieverwaltungsseite eine neue Registerkarte „Kategorieprodukte“ mit einem Produktraster hinzufügen, das dem Standardproduktraster der Kategorie entspricht.

Magento Category admin

Der einzige Unterschied besteht darin, dass ich dieses Raster benötige, um ausgewählte Produkte in einer benutzerdefinierten Tabelle mit den folgenden Feldern zu speichern:

1.id
2.product_id
3.category_id
4.Position

Dies ermöglicht mir dann, „vorgestellte Produkte“ mit separater Produktbestellung zu haben, wie im folgenden Wireframe gezeigt:

Screenshot der Unterkategorie mit den „empfohlenen Produkten“.Category ordering

Erste Gedanken

  1. Erstellen Sie eine benutzerdefinierte Registerkarte ähnlich wie
    Mage_Adminhtml_Block_Catalog_Category_Tab_Product
  2. Erstellen Sie einen Beobachter, um die Kategoriebeziehung zu speichern
    catalog_category_save_after
  3. Rufen Sie Produkt-IDs mit der aktuellen Kategorie-ID aus der benutzerdefinierten Tabelle ab und markieren Sie sie als ausgewählt
War es hilfreich?

Lösung

Überblick


Nachdem ich mir den Kopf zerbrochen hatte, baute ich endlich ein Modul.

Modelle
Es wurde ein Modell erstellt, das das Kategoriemodell erweitert, um eine benutzerdefinierte Entität zu vermeiden.

Beobachter

addCategoryEssentialBlock

Dieser Beobachter fügt unsere Registerkarte „Neue Produkte“ und das serialisierte Raster auf der Kategorieverwaltungsseite hinzu und hört sich die an adminhtml_catalog_category_tabs Ereignis.

saveCategoryEssentialData

Dieser Beobachter speichert die Kategorie-Essential-Produktbeziehung beim Speichern der Kategorie und hört sich die ancatalog_category_save_after Ereignis.

Code


Block

app/code/local/Lg/Essentials/Block/Adminhtml/Catalog/Category/Tab/Essential.php

class Lg_Essentials_Block_Adminhtml_Catalog_Category_Tab_Essential extends Mage_Adminhtml_Block_Widget_Grid
{

    /**
     * Set grid params
     */
    public function __construct()
    {
        parent::__construct();
        $this->setId('catalog_category_essential');
        $this->setDefaultSort('position');
        $this->setDefaultDir('ASC');
        $this->setUseAjax(true);
    }

    /**
     * Get current category
     * @return Mage_Catalog_Model_Category
     */
    public function getCategory()
    {
        return Mage::registry('current_category');
    }

    /**
     * Add filter
     * @param $column
     * @return $this
     */
    protected function _addColumnFilterToCollection($column)
    {
        if ($column->getId() == 'in_essentials') {
            $essentialIds = $this->_getSelectedEssentials();
            if (empty($essentialIds)) {
                $essentialIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('entity_id', array('in'=>$essentialIds));
            } else {
                if ($essentialIds) {
                    $this->getCollection()->addFieldToFilter('entity_id', array('nin'=>$essentialIds));
                }
            }
        } else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }

    /**
     * Prepare the collection
     * @return Mage_Adminhtml_Block_Widget_Grid
     * @throws Exception
     */
    protected function _prepareCollection()
    {
        if ($this->getCategory()->getId()) {
            $this->setDefaultFilter(array('in_essentials'=>1));
        }
        $collection = Mage::getModel('catalog/product')->getCollection()
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('sku')
            ->addAttributeToSelect('price')
            ->addStoreFilter($this->getRequest()->getParam('store'))
            ->joinField(
                'position',
                'lg_essentials/category_essential',
                'position',
                'product_id=entity_id',
                'category_id='.(int) $this->getRequest()->getParam('id', 0),
                'left'
            );

        $this->setCollection($collection);

        if ($this->getCategory()->getProductsReadonly()) {
            $essentialIds = $this->_getSelectedEssentials();
            if (empty($essentialIds)) {
                $essentialIds = 0;
            }
            $this->getCollection()->addFieldToFilter('entity_id', array('in'=>$essentialIds));
        }

        return parent::_prepareCollection();
    }

    /**
     * Prepare the columns
     * @return $this
     * @throws Exception
     */
    protected function _prepareColumns()
    {

        if (!$this->getCategory()->getProductsReadonly()) {
            $this->addColumn(
                'in_essentials',
                array(
                    'header_css_class' => 'a-center',
                    'type'      => 'checkbox',
                    'name'      => 'in_essentials',
                    'values'    => $this->_getSelectedEssentials(),
                    'align'     => 'center',
                    'index'     => 'entity_id'
                ));
        }
        $this->addColumn(
            'entity_id',
            array(
                'header' => Mage::helper('lg_essentials')->__('ID'),
                'sortable'  => true,
                'width'     => '60',
                'index'     => 'entity_id'
            )
        );
        $this->addColumn('name', array(
            'header'    => Mage::helper('lg_essentials')->__('Name'),
            'index'     => 'name'
        ));
        $this->addColumn('sku', array(
            'header'    => Mage::helper('lg_essentials')->__('SKU'),
            'width'     => '80',
            'index'     => 'sku'
        ));
        $this->addColumn('price', array(
            'header'    => Mage::helper('lg_essentials')->__('Price'),
            'type'  => 'currency',
            'width'     => '1',
            'currency_code' => (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE),
            'index'     => 'price'
        ));
        $this->addColumn(
            'position',
            array(
                'header'         => Mage::helper('lg_essentials')->__('Position'),
                'width'     => '1',
                'type'      => 'number',
                'index'     => 'position',
                'editable'  => !$this->getCategory()->getProductsReadonly()
            )
        );
        return parent::_prepareColumns();
    }

    /**
     * Get grid url
     * @return string
     */
    public function getGridUrl()
    {
        return $this->getUrl(
            'adminhtml/essentials_essential_catalog_category/essentialsgrid',
            array(
                'id'=>$this->getCategory()->getId()
            )
        );
    }

    /**
     * Get list of selected Essential Ids
     * @return array
     */
    protected function _getSelectedEssentials()
    {
        $essential = Mage::getModel('lg_essentials/category');
        $essentials = $this->getCategoryEssentials();
        if (!is_array($essentials)) {
            $essentials = $essential->getEssentialsPosition($this->getCategory());
            return array_keys($essentials);
        }
        return $essentials;
    }

    /**
     * Get list of selected Essential Id & positions
     * @return array
     */
    public function getSelectedEssentials()
    {
        $essentials = array();
        $selected = Mage::getModel('lg_essentials/category')->getEssentialsPosition(Mage::registry('current_category'));
        if (!is_array($selected)) {
            $selected = array();
        }
        foreach ($selected as $essentialId => $position) {
            $essentials[$essentialId] = array('position' => $position);
        }
        return $essentials;
    }
}

app/code/local/Lg/Essentials/Block/Catalog/Category/List/Essential.php

class Lg_Essentials_Block_Catalog_Category_List_Essential extends Mage_Core_Block_Template
{
    /**
     * Get the list of Essentials
     * @return Mage_Catalog_Model_Resource_Product_Collection
     */
    public function getEssentialProductsCollection()
    {
        $category = Mage::registry('current_category');

        $collection = Mage::getModel('catalog/product')->getCollection()
            ->addAttributeToSelect('name')
            ->addAttributeToSelect('sku')
            ->addAttributeToSelect('price')
            ->joinField(
                'position',
                'lg_essentials/category_essential',
                'position',
                'product_id=entity_id',
                'at_position.category_id='.(int) $category->getId(),
                'right'
            );

        $collection->addOrder('position', 'asc');

        return $collection;
    }
}

Controller

app/code/local/Lg/Essentials/controllers/Adminhtml/Essentials/Essential/Catalog/CategoryController.php

require_once ("Mage/Adminhtml/controllers/Catalog/CategoryController.php");

class Lg_Essentials_Adminhtml_Essentials_Essential_Catalog_CategoryController
extends Mage_Adminhtml_Catalog_CategoryController
{
    /**
     * construct
     */
    protected function _construct()
    {
    // Define module dependent translate
    $this->setUsedModuleName('Lg_Essentials');
    }

    /**
     * Essentials grid in category page
     */
    public function essentialsgridAction()
    {
    $this->_initCategory();
    $this->loadLayout();
    $this->getLayout()->getBlock('category.edit.tab.essential')
    ->setCategoryEssentials($this->getRequest()->getPost('category_essentials', null));
    $this->renderLayout();
    }
}

usw

app/code/local/Lg/Essentials/etc/config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Lg_Essentials>
            <version>0.1.0</version>
        </Lg_Essentials>
    </modules>
    <global>
        <resources>
            <lg_essentials_setup>
                <setup>
                    <module>Lg_Essentials</module>
                    <class>Lg_Essentials_Model_Resource_Setup</class>
                </setup>
            </lg_essentials_setup>
        </resources>
        <blocks>
            <lg_essentials>
                <class>Lg_Essentials_Block</class>
            </lg_essentials>
        </blocks>
        <helpers>
            <lg_essentials>
                <class>Lg_Essentials_Helper</class>
            </lg_essentials>
        </helpers>
        <models>
            <lg_essentials>
                <class>Lg_Essentials_Model</class>
                <resourceModel>lg_essentials_resource</resourceModel>
            </lg_essentials>
            <lg_essentials_resource>
                <class>Lg_Essentials_Model_Resource</class>
                <entities>
                    <category_essential>
                        <table>lg_essentials_category_essential</table>
                    </category_essential>
                </entities>
            </lg_essentials_resource>
        </models>
    </global>
    <adminhtml>
        <layout>
            <updates>
                <lg_essentials>
                    <file>lg/essentials.xml</file>
                </lg_essentials>
            </updates>
        </layout>
        <events>
            <adminhtml_catalog_category_tabs>
                <observers>
                    <lg_essentials_essential_category>
                        <type>singleton</type>
                        <class>lg_essentials/adminhtml_observer</class>
                        <method>addCategoryEssentialBlock</method>
                    </lg_essentials_essential_category>
                </observers>
            </adminhtml_catalog_category_tabs>
            <catalog_category_save_after>
                <observers>
                    <lg_essentials_essential_category>
                        <type>singleton</type>
                        <class>lg_essentials/adminhtml_observer</class>
                        <method>saveCategoryEssentialData</method>
                    </lg_essentials_essential_category>
                </observers>
            </catalog_category_save_after>
        </events>
    </adminhtml>
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <Lg_Essentials before="Mage_Adminhtml">Lg_Essentials_Adminhtml</Lg_Essentials>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
    <frontend>
        <layout>
            <updates>
                <lg_essentials>
                    <file>lg/essentials.xml</file>
                </lg_essentials>
            </updates>
        </layout>
    </frontend>
</config>

Helfer

app/code/local/Lg/Essentials/Helper/Data.php

class Lg_Essentials_Helper_Data extends Mage_Core_Helper_Abstract
{
}

Modell

app/code/local/Lg/Essentials/Model/Adminhtml/Observer.php

class Lg_Essentials_Model_Adminhtml_Observer
{
    /**
     * Add the Essential tab to categories
     * @param Varien_Event_Observer $observer
     * @return Lg_Essentials_Model_Adminhtml_Observer $this
     */
    public function addCategoryEssentialBlock($observer)
    {
        $tabs = $observer->getEvent()->getTabs();
        $content = $tabs->getLayout()->createBlock(
            'lg_essentials/adminhtml_catalog_category_tab_essential',
            'category.essential.grid'
        )->toHtml();
        $serializer = $tabs->getLayout()->createBlock(
            'adminhtml/widget_grid_serializer',
            'category.essential.grid.serializer'
        );
        $serializer->initSerializerBlock(
            'category.essential.grid',
            'getSelectedEssentials',
            'essentials',
            'category_essentials'
        );
        $serializer->addColumnInputName('position');
        $content .= $serializer->toHtml();
        $tabs->addTab(
            'essential',
            array(
                'label'   => Mage::helper('lg_essentials')->__('Essentials'),
                'content' => $content,
            )
        );
        return $this;
    }

    /**
     * Save category - essential relation
     * @param Varien_Event_Observer $observer
     * @return Lg_Essentials_Model_Adminhtml_Observer $this
     */
    public function saveCategoryEssentialData($observer)
    {
        $post = Mage::app()->getRequest()->getPost('essentials', -1);

        if ($post != '-1') {
            $post = Mage::helper('adminhtml/js')->decodeGridSerializedInput($post);
            $category = Mage::registry('category');
            $category->setPostedEssentials($post);
            $essentialResource = Mage::getResourceModel('lg_essentials/category');
            $essentialResource->saveCategoryEssentials($category);
        }
        return $this;
    }
}

app/code/local/Lg/Essentials/Model/Resource/Category.php

class Lg_Essentials_Model_Resource_Category extends Mage_Catalog_Model_Resource_Category
{
    /**
     * Save category essentials relation
     * @param Mage_Catalog_Model_Category $category
     * @return Mage_Catalog_Model_Resource_Category
     */
    public function saveCategoryEssentials($category)
    {
        $categoryEssentialTable = $this->getTable('lg_essentials/category_essential');

        $category->setIsChangedEssentialList(false);
        $id = $category->getId();
        /**
         * new category-essential relationships
         */
        $products = $category->getPostedEssentials();

        /**
         * Example re-save category
         */
        if ($products === null) {
            return $this;
        }

        /**
         * old category-essential relationships
         */
        $oldProducts = Mage::getModel('lg_essentials/category')->getEssentialsPosition($category);

        $insert = array_diff_key($products, $oldProducts);
        $delete = array_diff_key($oldProducts, $products);

        /**
         * Find product ids which are presented in both arrays
         * and saved before (check $oldProducts array)
         */
        $update = array_intersect_key($products, $oldProducts);

        if ($update) {
            $update = $this->cleanPositions($update);
        }

        $update = array_diff_assoc($update, $oldProducts);

        $adapter = $this->_getWriteAdapter();

        /**
         * Delete essentials from category
         */
        if (!empty($delete)) {
            $cond = array(
                'product_id IN(?)' => array_keys($delete),
                'category_id=?' => $id
            );
            $adapter->delete($categoryEssentialTable, $cond);
        }

        /**
         * Add essentials to category
         */
        if (!empty($insert)) {
            $data = array();
            foreach ($insert as $productId => $position) {
                $data[] = array(
                    'category_id' => (int)$id,
                    'product_id'  => (int)$productId,
                    'position'    => (int)$position['position']
                );
            }
            $adapter->insertMultiple($categoryEssentialTable, $data);
        }

        /**
         * Update essential positions in category
         */
        if (!empty($update)) {
            foreach ($update as $productId => $position) {
                $where = array(
                    'category_id = ?'=> (int)$id,
                    'product_id = ?' => (int)$productId
                );
                $bind  = array('position' => (int)$position);
                $adapter->update($categoryEssentialTable, $bind, $where);
            }
        }

        if (!empty($insert) || !empty($delete)) {
            $productIds = array_unique(array_merge(array_keys($insert), array_keys($delete)));
            Mage::dispatchEvent('catalog_category_change_essentials', array(
                'category'      => $category,
                'product_ids'   => $productIds
            ));
        }

        if (!empty($insert) || !empty($update) || !empty($delete)) {
            $category->setIsChangedEssentialList(true);

            /**
             * Setting affected essentials to category for third party engine index refresh
             */
            $productIds = array_keys($insert + $delete + $update);
            $category->setAffectedEssentialIds($productIds);
        }
        return $this;
    }

    /**
     * Get positions of associated to category essentials
     * @param Mage_Catalog_Model_Category $category
     * @return array
     */
    public function getEssentialsPosition($category)
    {
        $categoryEssentialTable = $this->getTable('lg_essentials/category_essential');

        $select = $this->_getWriteAdapter()->select()
            ->from($categoryEssentialTable, array('product_id', 'position'))
            ->where('category_id = :category_id');
        $bind = array('category_id' => (int)$category->getId());

        return $this->_getWriteAdapter()->fetchPairs($select, $bind);
    }

    /**
     * Get Essential count in category
     * @param Mage_Catalog_Model_Category $category
     * @return int
     */
    public function getEssentialCount($category)
    {
        $categoryEssentialTable = Mage::getSingleton('core/resource')->getTableName('lg_essentials/category_essential');

        $select = $this->getReadConnection()->select()
            ->from(
                array('main_table' => $categoryEssentialTable),
                array(new Zend_Db_Expr('COUNT(main_table.product_id)'))
            )
            ->where('main_table.category_id = :category_id');

        $bind = array('category_id' => (int)$category->getId());
        $counts = $this->getReadConnection()->fetchOne($select, $bind);

        return intval($counts);
    }

    /**
     * Clean Essentials positions
     * @param $products
     * @return array
     */
    protected function cleanPositions($products)
    {
        $cleanPositions = array();

        foreach ($products as $productid => $info) {
            $cleanPositions[$productid] = $info['position'];
        }

        return $cleanPositions;
    }
}

app/code/local/Lg/Essentials/Model/Resource/Setup.php

class Lg_Essentials_Model_Resource_Setup extends Mage_Catalog_Model_Resource_Setup
{
}

app/code/local/Lg/Essentials/Model/Category.php

class Lg_Essentials_Model_Category extends Mage_Catalog_Model_Category
{
    /**
     * Retrieve array of essential id's for category
     * array($productId => $position)
     * @param $category
     * @return array
     */
    public function getEssentialsPosition($category)
    {
        if (!$category->getId()) {
            return array();
        }
        $array = $category->getData('essentials_position');
        if (is_null($array)) {
            $array = Mage::getResourceModel('lg_essentials/category')->getEssentialsPosition($category);
            $category->setData('essentials_position', $array);
        }
        return $array;
    }

    /**
     * Retrieve count essentials of category
     * @param $category
     * @return int
     */
    public function getEssentialCount($category)
    {
        if (!$this->hasEssentialCount()) {
            $count = Mage::getResourceModel('lg_essentials/category')->getEssentialCount($category);
            $this->setData('essential_count', $count);
        }
        return $this->getData('essential_count');
    }
}

sql

app/code/local/Lg/Essentials/sql/lg_essentials_setup/install-0.1.0.php

/* @var $installer Mage_Catalog_Model_Resource_Setup */
$installer = $this;
$installer->startSetup();

/**
 * Create table 'lg_essentials/category_essential'
 */
$table = $installer->getConnection()
    ->newTable($installer->getTable('lg_essentials/category_essential'))
    ->addColumn(
        'category_id',
        Varien_Db_Ddl_Table::TYPE_INTEGER,
        null,
        array(
            'unsigned'  => true,
            'nullable'  => false,
            'primary'   => true,
            'default'   => '0',
        ),
        'Category ID'
    )
    ->addColumn(
        'product_id',
        Varien_Db_Ddl_Table::TYPE_INTEGER,
        null,
        array(
            'unsigned'  => true,
            'nullable'  => false,
            'primary'   => true,
            'default'   => '0',
        ),
        'Product ID'
    )
    ->addColumn(
        'position',
        Varien_Db_Ddl_Table::TYPE_INTEGER,
        null,
        array(
            'nullable'  => false,
            'default'   => '0',
        ),
        'Position'
    )
    ->addIndex(
        $installer->getIdxName(
            'lg_essentials/category_essential',
            array('product_id')
        ),
        array('product_id')
    )
    ->addForeignKey(
        $installer->getFkName(
            'lg_essentials/category_essential',
            'category_id',
            'catalog/category',
            'entity_id'
        ),
        'category_id',
        $installer->getTable('catalog/category'),
        'entity_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE,
        Varien_Db_Ddl_Table::ACTION_CASCADE
    )
    ->addForeignKey(
        $installer->getFkName(
            'lg_essentials/category_essential',
            'product_id',
            'catalog/product',
            'entity_id'
        ),
        'product_id',
        $installer->getTable('catalog/product'),
        'entity_id',
        Varien_Db_Ddl_Table::ACTION_CASCADE,
        Varien_Db_Ddl_Table::ACTION_CASCADE
    )
    ->addIndex(
        $this->getIdxName(
            'lg_essentials/category_essential',
            array('product_id', 'category_id'),
            Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
        ),
        array('product_id', 'category_id'),
        array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)
    )
    ->setComment('Essential To Category Linkage Table');
$installer->getConnection()->createTable($table);
$installer->endSetup();

adminthml

app/design/adminhtml/default/default/layout/lg/essentials.xml

<?xml version="1.0"?>
<layout>
    <adminhtml_essentials_essential_catalog_category_essentialsgrid>
        <block type="core/text_list" name="root" output="toHtml">
            <block type="lg_essentials/adminhtml_catalog_category_tab_essential" name="category.edit.tab.essential"/>
        </block>
    </adminhtml_essentials_essential_catalog_category_essentialsgrid>
</layout>

Frontend

app/design/frontend/base/default/layout/lg/essentials.xml

<?xml version="1.0"?>
<layout>
    <lg_essentials_category>
        <reference name="category.products">
            <block type="lg_essentials/catalog_category_list_essential" name="category.info.essentials"
                   as="category_essentials" template="lg/essentials/catalog/category/list/essential.phtml"/>
        </reference>
    </lg_essentials_category>
    <catalog_category_default>
        <update handle="lg_essentials_category" />
    </catalog_category_default>
    <catalog_category_layered>
        <update handle="lg_essentials_category" />
    </catalog_category_layered>
</layout>

app/design/frontend/base/default/template/lg/essentials/catalog/category/list/essential.phtml

<?php $essentials = $this->getEssentialProductsCollection();?>

<?php if ($essentials && $essentials->count() > 0) :?>
    <div class="box-collateral box-essentials box-up-sell">
        <h2>Essentials</h2>
        <?php foreach ($essentials as $_essential) : ?>
            <div class="item">
                <?php echo $_essential->getName();?>
            <br />
            </div>
        <?php endforeach; ?>
    </div>
<?php endif;?>

app/etc/modules/Lg_Essentials.xml

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

Andere Tipps

Es ist nicht klar, wie Ihre benutzerdefinierte Registerkarte aussehen soll.Sieht es mit dem Category Products identisch aus, dient nur einen anderen Zweck?

Wenn ja, können Ihre anfänglichen Gedanken gut klingen.Erstellen Sie eine neue Klasse für Ihre benutzerdefinierte Registerkarte.Mage_Adminhtml_Block_Catalog_Category_Tabs::_prepareLayout zeigt Ihnen eine Möglichkeit, eine neue Registerkarte hinzuzufügen.Sie werden sehen, dass diese Methode GEFIRTACDICETAGCODE feuert, die ein Beobachter anschließen kann, um eine andere Registerkarte hinzuzufügen. '

Um die benutzerdefinierten Daten zu speichern, denke ich, dass es gut ist, die "Kategorieaktion speichern" umzuschreiben, sodass Sie die geposteten Daten für Ihre benutzerdefinierte Tabelle abfangen und sie entsprechend speichern können.Ich bin nicht sicher, wie Sie die benutzerdefinierten Daten von adminhtml_catalog_category_tabs abrufen würden, wenn Sie sich dafür entscheiden, verschiedene Produkte unter Ihrer benutzerdefinierten Tab vs. catalog_category_save_after-Registerkarte auszuwählen.

Category Products Beobachter wird nur funktionieren, wenn Ihre benutzerdefinierte Registerkarte und der generationspflichtigen> immer die gleichen Produkte haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit magento.stackexchange
scroll top