我想在类别管理页面上添加一个新的类别产品选项卡,其产品网格与默认类别产品网格相同。

Magento Category admin

唯一的区别是,我需要这个网格将选定的产品保存在具有以下字段的自定义表中:

1.id
2.产品_id
3.分类_id
4.职位

然后,这将允许我拥有具有单独产品订购的"特色产品",如下面的线框所示:

显示"特色产品"的子类别截图。Category ordering

最初的想法

  1. 构建类似于以下内容的自定义选项卡
    Mage_Adminhtml_Block_Catalog_Category_Tab_Product
  2. 创建一个观察者来保存类别关系
    catalog_category_save_after
  3. 从自定义表中获取具有当前类别id的产品id,并将其标记为所选
有帮助吗?

解决方案

概述


在抓住我的头后,我终于建造了一个模块。

models
创建了一个模型,它扩展了类别模型以避免具有自定义实体。

观察者

addCategoryessentialBlock

此观察者在类别管理页面中添加我们的新产品选项卡和序列化网格,并侦听adminhtml_catalog_category_tabs事件。

saveCategoryessentialData

此观察者将类别 - Essentials产品相关性保存保存并侦听 catalog_category_save_after事件。

代码


app / code / local / lg / Essentials / block / adminhtml / catalog / category / tab / enderent.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;
    }
}
.

控制器

app / code / local / lg / Essentials / controller / 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();
    }
}
.

等等

app / code / local / lg / cenfients / 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>
.

辅助助手

app / code / local / lg / Essentials / Helper / data.php

class Lg_Essentials_Helper_Data extends Mage_Core_Helper_Abstract
{
}
.

型号

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 /资源/ 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 / ensifals / 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 / encients.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>
.

前端

app / design / frontend / base /默认/ layout / lg / ensifals.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 /默认/模板/ lg / Essentials / Catalog / Category / list / ensigent.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>
.

其他提示

目前尚不清楚您的自定义选项卡应该是什么样子。它看起来和......一样吗? Category Products 但只是为了不同的目的?

如果是这样,你最初的想法听起来不错。为自定义选项卡创建一个新类。 Mage_Adminhtml_Block_Catalog_Category_Tabs::_prepareLayout 向您展示添加新选项卡的一种方法。你会看到这个方法被触发 adminhtml_catalog_category_tabs, ,观察者可以挂接到该选项卡上以添加另一个选项卡。'

为了保存自定义数据,我认为重写"保存类别操作"会很好,这样您就可以截取自定义表的发布数据并相应地保存它们。我不确定您将如何从中检索自定义数据 catalog_category_save_after 如果您决定在自定义选项卡下选择不同的产品。 Category Products 标签。

atalog_category_save_after 观察员将 只有 工作,如果你的自定义选项卡和 Category Products 永远如此 有相同的产品。

许可以下: CC-BY-SA归因
scroll top