カスタムモジュールでProduct 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で生成されたものからコピー/貼り付け(およびファイル名を変更)したものです。これを使用して、エンティティを製品にリンクすることを心配する必要なく、完全なモジュールを作成できます。UIで「エンティティを製品にリンクする:はい」と言うだけです。


これはスパムではありません。延長は無料です。


2
これに賛成した人が全部読んだら、私はただ興味があります:)。
マリウス

Hats Off Buddyあなたはすりおろしています:)私はこれを試して、問題があったらあなたに教えます:)
Keyul Shah

質問に賛成票を投じた人がいるかどうかも知りたいです。
Keyul Shah 2014

私はこのコードを使用し、それはうまく機能しています。:)
Keyul Shah

入力非表示フィールドにデータベース値を設定する方法
ND17
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.