Как создать блок сериализатора Grid Product In в пользовательском модуле

8

Я хочу создать Grid Serializerфункциональность, аналогичную категории «Управление»

Если кто-нибудь создаст этот тип функциональности, пожалуйста, направьте меня.

Кейул Шах
источник

Ответы:

15

Предполагая, что у вас есть модуль без отношения продукта здесь, это то, что вам нужно в дополнение.
Сначала создайте таблицу отношений между вашей сущностью и продуктами. Добавьте это config.xmlвнутриglobal/models/[module]_resource/entities

<[entity]_product>
    <table>[entity]_product</table>
</[entity]_product>

Добавьте это в один из upgrade scripts.

$table = $this->getConnection()
    ->newTable($this->getTable('[module]/[entity]_product'))
    ->addColumn('rel_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned'  => true,
        'identity'  => true,
        'nullable'  => false,
        'primary'   => true,
        ), 'Relation ID')
    ->addColumn('[entity]_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
        'unsigned'  => true,
        'nullable'  => false,
        'default'   => '0',
    ), '[Entity] 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('[module]/[entity]_product', array('product_id')), array('product_id'))
    ->addForeignKey($this->getFkName('[module]/[entity]_product', '[entity]_id', '[module]/[entity]', 'entity_id'), '[entity]_id', $this->getTable('[module]/[entity]'), 'entity_id', Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
    ->addForeignKey($this->getFkName('[module]/[entity]_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('[Entity] to Product Linkage Table');
$this->getConnection()->createTable($table);

Теперь создайте блок сетки. [Namespace]/[Module]/Block/Adminhtml/[Entity]/Edit/Tab/Product.php

<?php
class [Namespace]_[Module]_Block_Adminhtml_[Entity]_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->get[Entity]()->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->get[Entity]()->getId()){
            $constraint = '{{table}}.[entity]_id='.$this->get[Entity]()->getId();
        }
        else{
            $constraint = '{{table}}.[entity]_id=0';
        }
        $collection->joinField('position',
            '[module]/[entity]_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->get[Entity]Products();
        if (!is_array($products)) {
            $products = array_keys($this->getSelectedProducts());
        }
        return $products;
    }
    public function getSelectedProducts() {
        $products = array();
        $selected = Mage::registry('current_[entity]')->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->get[Entity]()->getId()
        ));
    }
    public function get[Entity](){
        return Mage::registry('current_[entity]');
    }
    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;
    }
}

Теперь добавьте эту вкладку в список вкладок. В [Namespace]_[Module]_Block_Adminhtml_[Entity]_Edit_Tabs::_beforeToHtmlдобавление это ниже основной вкладки.

$this->addTab('products', array(
    'label' => Mage::helper('[module]')->__('Associated products'),
    'url'   => $this->getUrl('*/*/products', array('_current' => true)),
    'class'    => 'ajax'
));

Теперь вам нужны действия контроллера для обработки продуктов.

Добавьте эти методы в контроллер администратора для вашей сущности:

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('[entity].edit.tab.product')
        ->set[Entity]Products($this->getRequest()->getPost('[entity]_products', null));
    $this->renderLayout();
}
public function productsgridAction(){
    $this->_init[Entity]();
    $this->loadLayout();
    $this->getLayout()->getBlock('[entity].edit.tab.product')
        ->set[Entity]Products($this->getRequest()->getPost('[entity]_products', null));
    $this->renderLayout();
}

Теперь макет для этих 2-х действий. В файле макета администратора для вашего модуля добавьте эти 2 маркера.

<adminhtml_[module]_[entity]_products>
    <block type="core/text_list" name="root" output="toHtml">
        <block type="[module]/adminhtml_[entity]_edit_tab_product" name="[entity].edit.tab.product"/>
        <block type="adminhtml/widget_grid_serializer" name="product_grid_serializer">
            <reference name="product_grid_serializer">
                <action method="initSerializerBlock">
                    <grid_block_name>[entity].edit.tab.product</grid_block_name>
                        <data_callback>getSelectedProducts</data_callback>
                        <hidden_input_name>products</hidden_input_name>
                        <reload_param_name>[entity]_products</reload_param_name>
                </action>
                <action method="addColumnInputName">
                    <input_name>position</input_name>
                </action>
            </reference>
        </block>
    </block>
</adminhtml_[module]_[entity]_products>
<adminhtml_[module]_[entity]_productsgrid>
    <block type="core/text_list" name="root" output="toHtml">
        <block type="[module]/adminhtml_[entity]_edit_tab_product" name="[entity].edit.tab.product"/>
    </block>
</adminhtml_[module]_[entity]_productsgrid>

Теперь сохраняем данные. В saveActionвашем админ-контролере добавьте это прямо перед вызовом$[entity]->save()

$products = $this->getRequest()->getPost('products', -1);
if ($products != -1) {
    $[entity]->setProductsData(Mage::helper('adminhtml/js')->decodeGridSerializedInput($products));
}

В вашей модели сущности добавьте эти методы и переменную-член, которая будет обрабатывать отношение продукта:

protected $_productInstance = null;
public function getProductInstance(){
    if (!$this->_productInstance) {
        $this->_productInstance = Mage::getSingleton('[module]/[entity]_product');
    }
    return $this->_productInstance;
}
protected function _afterSave() {
    $this->getProductInstance()->save[Entity]Relation($this);
    return parent::_afterSave();
}
public function getSelectedProducts(){
    if (!$this->hasSelectedProducts()) {
        $products = array();
        foreach ($this->getSelectedProductsCollection() as $product) {
            $products[] = $product;
        }
        $this->setSelectedProducts($products);
    }
    return $this->getData('selected_products');
}
public function getSelectedProductsCollection(){
    $collection = $this->getProductInstance()->getProductCollection($this);
    return $collection;
}

Теперь вам нужна модель отношения сущность-продукт.

Создайте [Namespace]/[Module]/Model/[Entity]/Product.php

<?php
class [Namespace]_[Module]_Model_[Entity]_Product
    extends Mage_Core_Model_Abstract {
    protected function _construct(){
        $this->_init('[module]/[entity]_product');
    }
    public function save[Entity]Relation($[entity]){
        $data = $[entity]->getProductsData();
        if (!is_null($data)) {
            $this->_getResource()->save[Entity]Relation($[entity], $data);
        }
        return $this;
    }
    public function getProductCollection($[entity]){
        $collection = Mage::getResourceModel('[module]/[entity]_product_collection')
            ->add[Entity]Filter($[entity]);
        return $collection;
    }
}

Вам также нужна модель ресурса. [Namespace]/[Module]/Model/Resource/[Entity]/Product.php

<?php
class [Namespace]_[Module]_Model_Resource_[Entity]_Product
    extends Mage_Core_Model_Resource_Db_Abstract {
    protected function  _construct(){
        $this->_init('[module]/[entity]_product', 'rel_id');
    }
    public function save[Entity]Relation($[entity], $data){
        if (!is_array($data)) {
            $data = array();
        }
        $deleteCondition = $this->_getWriteAdapter()->quoteInto('[entity]_id=?', $[entity]->getId());
        $this->_getWriteAdapter()->delete($this->getMainTable(), $deleteCondition);

        foreach ($data as $productId => $info) {
            $this->_getWriteAdapter()->insert($this->getMainTable(), array(
                '[entity]_id'      => $[entity]->getId(),
                'product_id'     => $productId,
                'position'      => @$info['position']
            ));
        }
        return $this;
    }
}

и модель коллекции ресурсов. Я обещаю, что это последний.[Namespace]/[Module]/Model/Resource/[Entity]/Product/Collection.php

<?php 
class [Namespace]_[Module]_Model_Resource_[Entity]_Product_Collection
    extends Mage_Catalog_Model_Resource_Product_Collection {
    protected $_joinedFields = false;
    public function joinFields(){
        if (!$this->_joinedFields){
            $this->getSelect()->join(
                array('related' => $this->getTable('[module]/[entity]_product')),
                'related.product_id = e.entity_id',
                array('position')
            );
            $this->_joinedFields = true;
        }
        return $this;
    }
    public function add[Entity]Filter($[entity]){
        if ($[entity] instanceof [Namespace]_[Module]_Model_[Entity]){
            $[entity] = $[entity]->getId();
        }
        if (!$this->_joinedFields){
            $this->joinFields();
        }
        $this->getSelect()->where('related.[entity]_id = ?', $[entity]);
        return $this;
    }
}

Все , что вам нужно сделать , это заменить значения между []( [Namespace], [Module], [module]...) с реальными значениями.
Вы можете столкнуться с некоторыми ошибками, потому что способ, которым вы структурировали свой модуль, может немного отличаться от того, что я имею в виду. Но с некоторыми отладками и изменениями вы можете заставить его работать. Все тяжелые работы там.

Вот и все.

Примечание. Приведенный выше код был скопирован / вставлен (и переименован в имена файлов) из того, что было сгенерировано с помощью UMC . Вы можете использовать это для создания своего полного модуля, не беспокоясь о том, чтобы связать свою сущность с продуктами. Вы просто говорите в интерфейсе «Связать сущность с продуктами: да».


Это не спам. Расширение бесплатно.

Мариус
источник
2
Мне просто любопытно, если человек (ы), которые проголосовали за это, прочитайте все это :).
Мариус
Hats Off Buddy, ты Grate :) Я попробую это и дам тебе, если у меня возникнут проблемы :)
Keyul Shah
Мне также интересно, если человек (ы), кто проголосовал за вопросы.
Кейул Шах
Я использую этот код, и он работает. Очень хорошо. Большое спасибо, мужчины. :)
Кейул Шах
Как установить значение базы данных во входном скрытом поле
ND17