Filtering a text-type column with MySQL-computed values in Magento Admin Grid

一世执手 提交于 2020-01-13 19:07:55

问题


Say one column in grid has computed values:

setCollection():

'refunded' => new Zend_Db_Expr("IF(qty_refunded > 0, 'Yes', 'No')"),

_prepareColumns():

$this->addColumnAfter('refunded', array(
    'header' => Mage::helper('helper')->__('Refunded'),
    'index'  => 'refunded',
    'type'   => 'text',
), 'qty');

What and how must one change in order to have columns with "yes" values, in case admin types "yes" then filters?


回答1:


Adminhtml grid columns have a filter property which specifies a block class. For boolean yes/no fields that would usually be adminhtml/widget_grid_column_filter_select.
It would be used automatically if your field type would be 'options'.

Try this in _prepareCollection():

'refunded' => new Zend_Db_Expr("IF(qty_refunded > 0, 1, 0)"),

And in _prepareColumns() use:

$this->addColumnAfter('refunded', array(
    'header'  => Mage::helper('helper')->__('Refunded'),
    'index'   => 'refunded',
    'type'    => 'options',
    'options' => array(0 => $this->__('No'), 1 => $this->__('Yes'))
), 'qty');

This should still render your values as "Yes" and "No" in the Column, and you would get the select with the appropriate options as a filter dropdown.

This alone won't be enough since the column with the computed value can't be referenced directly in the WHERE clause by MySQL. Magento provides two options to work around that.

Column filter blocks have a method getCondition() which return a condition that will be used to filter the collection. See Mage_Adminhtml_Block_Widget_Grid_Column_Filter_Abstract::getCondition() for an example.
So if you need to customize the SQL used to execute the filter, create your own column filter block extending Mage_Adminhtml_Block_Widget_Grid_Column_Filter_Select and adjust the returned condition as needed, i.e. use the same computed value to match against.
Your custom filter can be specified for the column like this in the addColumn() definition:

    'type'    => 'options',
    'options' => array(0 => $this->__('No'), 1 => $this->__('Yes')),
    'filter'  => 'your_module/adminhtml_widget_grid_column_filter_custom',

If you prefere to work outside of the limitations of Magento's ORM filter syntax, you can modify the collections select directly by using a filter callback:

    'type'    => 'options',
    'options' => array(0 => $this->__('No'), 1 => $this->__('Yes')),
    'filter_condition_callback' => array($this, '_applyMyFilter'),

The callback receives the collection and the column as arguments. Here is a simple example for that method:

protected function _applyMyFilter(Varien_Data_Collection_Db $collection, Mage_Adminhtml_Block_Widget_Grid_Column $column)
{
    $select = $collection->getSelect();
    $field = $column->getIndex();
    $value = $column->getFilter()->getValue();
    $select->having("$field=?, $value);
}

Needless to say that both approaches (filtering against the computed value) is very inefficient in MySQL. But maybe that's no a problem for you in this case.




回答2:


I'll post a working example, but I'll choose Vinai's answer for being so detailed.

In Grid.php:

protected function _addColumnFilterToCollection($column) 
{
    if ($column->getId() == 'refunded' && $column->getFilter()->getValue()) {
        $val        = $column->getFilter()->getValue();
        $comparison = ($val === "No") ? 'lteq' : 'gt'; // lteg: <=; gt: >

        $this->getCollection()->addFieldToFilter('ois.qty_refunded', array($comparison => 0));
    } else {
        parent::_addColumnFilterToCollection($column);
    }

    return $this;
}


来源:https://stackoverflow.com/questions/9530287/filtering-a-text-type-column-with-mysql-computed-values-in-magento-admin-grid

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!