Cómo crear el bloque serializador de cuadrícula de producto en el módulo personalizado

Respuestas:

15

Suponiendo que tiene el módulo sin la relación del producto, aquí es lo que necesita además.
Primero cree una tabla de relaciones entre su entidad y los productos. Agregue esto config.xmldentro delglobal/models/[module]_resource/entities

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

Agregue esto en uno de los 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);

Ahora crea el bloque de cuadrícula. [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;
    }
}

Ahora agregue esta pestaña en la lista de pestañas. En [Namespace]_[Module]_Block_Adminhtml_[Entity]_Edit_Tabs::_beforeToHtmlagregar esto debajo de la pestaña principal.

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

Ahora necesita las acciones del controlador para manejar los productos.

Agregue estos métodos al controlador de administración para su entidad:

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();
}

Ahora el diseño para estas 2 acciones. En el archivo de diseño de administración para su módulo, agregue estos 2 identificadores.

<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>

Ahora guardando los datos. En el saveActioncontrolador de administración, agregue esto justo antes de llamar$[entity]->save()

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

En su modelo de entidad, agregue estos métodos y una variable miembro que procesará la relación del producto:

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;
}

Ahora necesita el modelo de relación entidad-producto.

Crear [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;
    }
}

También necesita un modelo de recurso. [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;
    }
}

y un modelo de recurso de colección. Prometo que este es el último.[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;
    }
}

Todo lo que necesita hacer es reemplazar los valores entre []( [Namespace], [Module], [module], ...) con sus valores reales.
Puede encontrar algunos errores, porque la forma en que estructuró su módulo puede ser un poco diferente de lo que tengo en mente. Pero con algunas depuraciones y cambios, puede hacer que funcione. Todo el trabajo pesado está ahí.

Eso es.

Nota: El código anterior fue copiado / pegado (y renombró los nombres de los archivos) de lo que se generó con UMC . Puede usar eso para crear su módulo completo sin tener que preocuparse por vincular su entidad a los productos. Simplemente dice en la interfaz de usuario "Vincular entidad a productos: Sí".


Esto no es spam. La extensión es gratuita.

Marius
fuente
2
Tengo curiosidad por saber si la persona (s) que votó por esto, lo leyó todo :).
Marius
Me
quito el
También tengo curiosidad si la (s) persona (s) que votaron las preguntas.
Keyul Shah
Yo uso este código y está funcionando Muy bien Muchas gracias hombres. :)
Keyul Shah
Cómo establecer el valor de la base de datos en el campo oculto de entrada
ND17