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;
}
}
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".
在我的模块集合 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;
}
}