Magento Custom Collection 阻止正确的 Massaction 复选框选择

Magento Custom Collection Prevents Proper Massaction Checkbox Selection

Magento 1.7.0.2 - 我通过扩展目录产品 Collection 创建了自定义 collection。 collection 本质上是什么:一个 collection 独特的产品组合,如果任何产品有自定义选项,那么每个独特的产品组合 id/option id 是 collection 中的另一个项目. collection 和计数工作正常。

但是,用于批量操作复选框选择的 "Select All" 按钮仅选择具有产品 ID 的行,而不选择 product_id 与 option_id 连接的行,如下图。

这是我的 collection class。

<?php 

class Lightsnholsters_Inventory_Model_Resource_Catalog_Product_Collection extends Mage_Catalog_Model_Resource_Product_Collection
{
  public function getSelectCountSql()
  {   
      $this->_renderFilters();
      $countSelect = clone $this->getSelect();
      $countSelect->reset(Zend_Db_Select::ORDER);
      $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
      $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
      $countSelect->reset(Zend_Db_Select::COLUMNS);

      // Count doesn't work with group by columns keep the group by 
      if(count($this->getSelect()->getPart(Zend_Db_Select::GROUP)) > 0) {
          $countSelect->reset(Zend_Db_Select::GROUP);
          $countSelect->distinct(true);
          $group = $this->getSelect()->getPart(Zend_Db_Select::GROUP);
          $countSelect->columns("COUNT(DISTINCT ".implode(", ", $group).")");
      } else {
          $countSelect->columns('COUNT(*)');
      }
      return $countSelect;
  }

  protected function _initSelect()
  {
      parent::_initSelect();
      $this->joinAttribute('name','catalog_product/name','entity_id');                  

      $this->getSelect()->reset(Zend_Db_Select::COLUMNS);

      $this->getSelect()->joinLeft(
          array('opt' => $this->getTable('catalog/product_option')),
          "e.entity_id = opt.product_id AND opt.type IN('radio','drop_down')",
          array(''));

      $this->getSelect()->joinLeft(
          array('opt_val' => $this->getTable('catalog/product_option_type_value')),
          "opt.option_id = opt_val.option_id AND opt_val.sku != '' AND opt_val.sku IS NOT NULL",
          array('entity_id' => new Zend_Db_Expr("CONCAT_WS('_',e.entity_id,opt_val.option_type_id)"),
                'option_type_id' => new Zend_Db_Expr("IF(opt_val.option_type_id > 0, opt_val.option_type_id,0)")));

      $this->getSelect()->joinLeft(
          array('opt_prc' => $this->getTable('catalog/product_option_type_price')),
          "opt_val.option_type_id = opt_prc.option_type_id AND opt_prc.store_id = {$this->getStoreId()}",
          array(''));

      $this->getSelect()->joinLeft(
          array('opt_ttl' => $this->getTable('catalog/product_option_type_title')),
          "opt_val.option_type_id = opt_ttl.option_type_id AND opt_ttl.store_id = {$this->getStoreId()}",
          array('name' => new Zend_Db_Expr("CONCAT_WS(' ',at_name.value,title)")));

      return $this;
  }  
}

这是我在网格中使用的massaction代码class

  protected function _prepareMassaction()
  {
    $this->setMassactionIdField('entity_id');
    $this->setMassactionIdFilter('entity_id');
    $this->getMassactionBlock()->setFormFieldName('entity_id');

    $this->getMassactionBlock()->addItem('updateAttributes', array(
      'label'   => $this->__('Update Attributes'),
      'url'     => $this->getUrl('*/*/massUpdateAttributes'),
    ));

    $statuses = array(
      array('label' => '',                    'value'=>''),
      array('label' => $this->__('Disabled'), 'value'=>0 ),
      array('label' => $this->__('Enabled') , 'value'=>1 )
    );
    $this->getMassactionBlock()->addItem('status', array(
         'label'=> $this->__('Change status'),
         'url'  => $this->getUrl('*/*/massStatus', array('_current'=>true)),
         'additional' => array(
             'visibility'  => array(
             'name'   => 'status',
             'type'   => 'select',
             'class'  => 'required-entry',
             'label'  => $this->__('Status'),
             'values' => $statuses
           )
         )
    ));

    Mage::dispatchEvent('lightsnholsters_inventory_autolist_grid_massaction_prepare', array('block' => $this));
    return $this;
  } 

似乎我在 $this->setMassactionIdField('entity_id'); 中输入的任何字段都被完全忽略了。

我的目标是,当我单击 "Select All" 时,所有复选框都被选中,而不仅仅是那些没有 option_id 连接的复选框。

感谢您的帮助。

我重新审视了这个问题,并弄清楚了为什么我的集合中包含使用 ->joinLeft 和动态创建的 id 列有目的地动态创建的行不允许 massaction 块 "Select All" 正确 select 单击时的复选框。

这是因为当我扩展 Mage_Catalog_Model_Resource_Collection 以用作我自己的自定义集合的基础时,class 已经覆盖了 Varien_Data_Collection 的 getAllIds() 方法,massaction当我们点击 "Select All".

时,块用于确定我们实际想要 select 的 ID

在我的模块集合 class 中,我扩展了 Magento 的产品集合,我只需要创建自己的 getAllIds() 方法即可完全覆盖该方法的父版本。

简而言之,一切正常,请参阅下面的代码。

<?php 

class Lightsnholsters_Inventory_Model_Resource_Catalog_Product_Collection extends Mage_Catalog_Model_Resource_Product_Collection
{
  /*
  *
  * we had to rewrite this function because the grid had the wrong count, which is actually why we created this class to begin with
  *
  */
  public function getSelectCountSql()
  {   
      $this->_renderFilters();
      $countSelect = clone $this->getSelect();
      $countSelect->reset(Zend_Db_Select::ORDER);
      $countSelect->reset(Zend_Db_Select::LIMIT_COUNT);
      $countSelect->reset(Zend_Db_Select::LIMIT_OFFSET);
      $countSelect->reset(Zend_Db_Select::COLUMNS);

      // Count doesn't work with group by columns keep the group by 
      if(count($this->getSelect()->getPart(Zend_Db_Select::GROUP)) > 0) {
          $countSelect->reset(Zend_Db_Select::GROUP);
          $countSelect->distinct(true);
          $group = $this->getSelect()->getPart(Zend_Db_Select::GROUP);
          $countSelect->columns("COUNT(DISTINCT ".implode(", ", $group).")");
      } else {
          $countSelect->columns('COUNT(*)');
      }
      return $countSelect;
  }

  protected function _initSelect()
  {
      parent::_initSelect();
      $this->joinAttribute('name','catalog_product/name','entity_id');                  

      $this->getSelect()->reset(Zend_Db_Select::COLUMNS);

      $this->getSelect()->joinLeft(
          array('opt' => $this->getTable('catalog/product_option')),
          "e.entity_id = opt.product_id AND opt.type IN('radio','drop_down')",
          array(''));

      $this->getSelect()->joinLeft(
          array('opt_val' => $this->getTable('catalog/product_option_type_value')),
          "opt.option_id = opt_val.option_id AND opt_val.sku != '' AND opt_val.sku IS NOT NULL",
          array('entity_id' => new Zend_Db_Expr("CONCAT_WS('_',e.entity_id,opt_val.option_type_id)"),
                'option_type_id' => new Zend_Db_Expr("IF(opt_val.option_type_id > 0, opt_val.option_type_id,0)")));

      $this->getSelect()->joinLeft(
          array('opt_prc' => $this->getTable('catalog/product_option_type_price')),
          "opt_val.option_type_id = opt_prc.option_type_id AND opt_prc.store_id = {$this->getStoreId()}",
          array(''));

      $this->getSelect()->joinLeft(
          array('opt_ttl' => $this->getTable('catalog/product_option_type_title')),
          "opt_val.option_type_id = opt_ttl.option_type_id AND opt_ttl.store_id = {$this->getStoreId()}",
          array('name' => new Zend_Db_Expr("CONCAT_WS(' ',at_name.value,title)")));

      return $this;
  }  

  /*
  *
  * we override the parent method for all ids because it does not fetch the proper ids for the massaction checkboxes
  *
  */
  public function getAllIds($limit = null, $offset = null)
  {
    $this->_renderFilters();
    $connection = $this->getConnection();
    $idsSelect = clone $this->getSelect();
    $idsSelect->reset(Zend_Db_Select::LIMIT_COUNT);
    $idsSelect->reset(Zend_Db_Select::LIMIT_OFFSET);    
    $statement = $connection->query($idsSelect);
    $ids = $statement->fetchAll(PDO::FETCH_COLUMN);
    return $ids;
  }  
}