在 Magento 的类别编辑页面中添加另一个带有产品网格的选项卡

Add another tab with Product Grid to Category edit page in Mangento

我正在尝试向包含另一个产品网格的类别编辑页面添加另一个选项卡。我需要这样做,因为我想向每个类别页面添加一个区域,其中包含在此网格中选择的产品。

谁能帮我完成这个模块?或者是否有更简单或现有的模块来执行此操作?

PS:非常感谢完整的代码:)

这是我到目前为止的进展: etc/config.xml

<?xml version="1.0"?>
<config>
  <modules>
    <Forideas_Promotion>
      <version>0.1.0</version>
    </Forideas_Promotion>
  </modules>
  <global>
    <resources>
        <forideas_promotion_setup>
            <setup>
                <module>Forideas_Promotion</module>
                <class>Forideas_Promotion_Model_Resource_Setup</class>
            </setup>
        </forideas_promotion_setup>
    </resources>
    <helpers>
      <promotion>
        <class>Forideas_Promotion_Helper</class>
      </promotion>
    </helpers>
    <models>
        <forideas_promotion>
            <class>Forideas_Promotion_Model</class>
        </forideas_promotion>
        <promotion_resource>
            <entities>
              <category_product>
                  <table>category_product</table>
              </category_product>
            </entities>
        </promotion_resource>
    </models>
    <events>
        <adminhtml_catalog_category_tabs>
            <observers>
                <forideas_promotion_observer>
                    <class>forideas_promotion/observer</class>
                    <method>addCategoryTab</method>
                </forideas_promotion_observer>
            </observers>
        </adminhtml_catalog_category_tabs>
    </events>
  </global>
  <adminhtml>
    <layout>
        <updates>
            <forideas_category_promotion>
                <file>forideas_promotion.xml</file>
            </forideas_category_promotion>
        </updates>
    </layout>
  </adminhtml>
  <admin>
      <routers>
          <adminhtml>
              <args>
                  <modules>
                      <Forideas_Promotion before="Mage_Adminhtml">Forideas_Promotion_Adminhtml</Forideas_Promotion>
                  </modules>
              </args>
          </adminhtml>
      </routers>
  </admin>
</config> 

Block/Adminhtml/Category/Edit/Tab/Product.php:

<?php
class Forideas_Promotion_Block_Adminhtml_Category_Edit_Tab_Product
    extends Mage_Adminhtml_Block_Widget_Grid {
    public function __construct(){
        parent::__construct();
        $this->setId('product_grid');
        $this->setDefaultSort('position');
        $this->setDefaultDir('ASC');
        $this->setUseAjax(true);
        if ($this->getCategory()->getId()) {
            $this->setDefaultFilter(array('in_products'=>1));
        }
    }
    protected function _prepareCollection() {
        $collection = Mage::getResourceModel('catalog/product_collection');
        $collection->addAttributeToSelect('price');
        $adminStore = Mage_Core_Model_App::ADMIN_STORE_ID;
        $collection->joinAttribute('product_name', 'catalog_product/name', 'entity_id', null, 'left', $adminStore);
        if ($this->getCategory()->getId()){
            $constraint = '{{table}}.category_id='.$this->getCategory()->getId();
        }
        else{
            $constraint = '{{table}}.category_id=0';
        }
        $collection->joinField('position',
            'promotion/category_product',
            'position',
            'product_id=entity_id',
            $constraint,
            'left');
        $this->setCollection($collection);
        parent::_prepareCollection();
        return $this;
    }
     protected function _prepareMassaction(){
        return $this;
    }
    protected function _prepareColumns(){
        $this->addColumn('in_products', array(
            'header_css_class'  => 'a-center',
            'type'  => 'checkbox',
            'name'  => 'in_products',
            'values'=> $this->_getSelectedProducts(),
            'align' => 'center',
            'index' => 'entity_id'
        ));
        $this->addColumn('product_name', array(
            'header'=> Mage::helper('catalog')->__('Name'),
            'align' => 'left',
            'index' => 'product_name',
        ));
        $this->addColumn('sku', array(
            'header'=> Mage::helper('catalog')->__('SKU'),
            'align' => 'left',
            'index' => 'sku',
        ));
        $this->addColumn('price', array(
            'header'=> Mage::helper('catalog')->__('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('catalog')->__('Position'),
            'name'  => 'position',
            'width' => 60,
            'type'  => 'number',
            'validate_class'=> 'validate-number',
            'index' => 'position',
            'editable'  => true,
        ));
    }
    protected function _getSelectedProducts(){
        $products = $this->getCategoryProducts();
        if (!is_array($products)) {
            $products = array_keys($this->getSelectedProducts());
        }
        return $products;
    }
    public function getSelectedProducts() {
        $products = array();
        $selected = Mage::registry('current_category')->getSelectedProducts();
        if (!is_array($selected)){
            $selected = array();
        }
        foreach ($selected as $product) {
            $products[$product->getId()] = array('position' => $product->getPosition());
        }
        return $products;
    }
    public function getRowUrl($item){
        return '#';
    }
    public function getGridUrl(){
        return $this->getUrl('*/*/productsGrid', array(
            'id'=>$this->getCategory()->getId()
        ));
    }
    public function getCategory(){
        return Mage::registry('current_category');
    }
    protected function _addColumnFilterToCollection($column){
        // Set custom filter for in product flag
        if ($column->getId() == 'in_products') {
            $productIds = $this->_getSelectedProducts();
            if (empty($productIds)) {
                $productIds = 0;
            }
            if ($column->getFilter()->getValue()) {
                $this->getCollection()->addFieldToFilter('entity_id', array('in'=>$productIds));
            }
            else {
                if($productIds) {
                    $this->getCollection()->addFieldToFilter('entity_id', array('nin'=>$productIds));
                }
            }
        }
        else {
            parent::_addColumnFilterToCollection($column);
        }
        return $this;
    }
}

controllers/Adminhtml/Promotion/Category/ProductController.php:

<?php

require_once ("Mage/Adminhtml/controllers/Catalog/ProductController.php");
class Forideas_Promotion_Adminhtml_Promotion_Category_ProductController extends Mage_Adminhtml_Catalog_ProductController
{

    public function productsAction(){
        //$this->_initEntity(); //if you don't have such a method then replace it with something that will get you the entity you are editing.
        $this->loadLayout();
        $this->getLayout()->getBlock('category.edit.tab.product')
            ->setCategoryProducts($this->getRequest()->getPost('category_products', null));
        $this->renderLayout();
    }
    public function productsgridAction(){
        //$this->_initCategory();
        $this->loadLayout();
        $this->getLayout()->getBlock('category.edit.tab.product')
            ->setCategoryProducts($this->getRequest()->getPost('category_products', null));
        $this->renderLayout();
    }

}

Model/Observer.php

<?php

class Forideas_Promotion_Model_Observer{


    public function addCategoryTab($observer)
    {
        $block = $observer->getEvent()->getTabs();

            $block->addTab('features', array(
                'label' => Mage::helper('catalog')->__('Some Label here'),

                'url'   => Mage::helper('adminhtml')->getUrl('adminhtml/promotion_category_product/productsgrid', array('_current' => true)),
                'class' => 'ajax', 
            ));


    }

}

sql/setup/install-0.1.0.php

$this->startSetup();

$table = $this->getConnection()
    ->newTable($this->getTable('promotion/category_product'))
    ->addColumn('rel_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned'  => true,
        'identity'  => true,
        'nullable'  => false,
        'primary'   => true,
        ), 'Relation ID')
    ->addColumn('category_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned'  => true,
        'nullable'  => false,
        'default'   => '0',
    ), 'Category ID')
    ->addColumn('product_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned'  => true,
        'nullable'  => false,
        'default'   => '0',
    ), 'Product ID')
    ->addColumn('position', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'nullable'  => false,
        'default'   => '0',
    ), 'Position')
    ->addIndex($this->getIdxName('promotion/category_product', array('product_id')), array('product_id'))
    ->addForeignKey($this->getFkName('promotion/category_product', 'category_id', 'promotion/category', 'entity_id'), 'category_id', $this->getTable('promotion/category'), 'entity_id', Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey($this->getFkName('promotion/category_product', 'product_id', 'catalog/product', 'entity_id'),    'product_id', $this->getTable('catalog/product'), 'entity_id', Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->setComment('Category to Product Linkage Table');
$this->getConnection()->createTable($table);

$this->endSetup();

不知道你上传这些代码的目的是什么。据我所知,它与您的问题无关。如果您想添加新标签,请执行以下操作:

config.xml

<adminhtml>
    <events>
        <adminhtml_catalog_category_tabs>
            <observers>
                <add_new_tab>
                    <type>singleton</type>
                    <class>company_module/observer</class>
                    <method>addNewCategoryTab</method>
                </add_new_tab>
            </observers>
        </adminhtml_catalog_category_tabs>
    </events>
</adminhtml>

Model/Observer.php

class Company_Module_Model_Observer
{
    public function addNewCategoryTab($observer)
    {
        $tabs = $observer->getTabs();
        $tabs->addTab('prod', array(
            'label'     => Mage::helper('catalog')->__('Other Products'),
            'content'   => $tabs->getLayout()->createBlock(
                'adminhtml/catalog_category_tab_product',
                'category.product.grid'
            )->toHtml(),
        ));
    }

比使用从 adminhtml/catalog_category_tab_product 扩展的块和重写的 _prepareCollection 方法。 (不要忘记将你的块放在 createBlock 方法中)

我找到了您 'ajax loader will not disappear' 问题的答案。这是因为从 AJAX 调用 return 得到的 HTML 实际上指的是原始 table、catalog_category_products_table。但是 Javascript 正在寻找您自己的 table 名称但找不到它,因此无限请等待加载器。

解决方案是创建您自己的扩展 Mage_Adminhtml_Catalog_CategoryController 的控制器,并在其中加载带有您的网格名称的您自己的块。然后,在扩展 Mage_Adminhtml_Block_Catalog_Category_Tab_Product 的块中,您将定义 getGridUrl() 和 return 新创建的控制器的路径。现在一切都会正常工作了。