Magento – Admin Grid Filtering on Joined Column

collection;gridjoin;

I have an admin grid that I'm using, and pulling in custom model and displaying. Everything works fine, and all columns can filter/sort, except when I try to use a column that is not inherent to my custom model. Specifically, I'm trying to use a join from my custom model to another custom table, and then from there to another custom table, all using flat tables.

I've included my _prepareCollection() and my _prepareColumns() functions for reference. I'm doing my joins in my _prepareCollection() function, and this is an acceptable solution for my grid if I can get filtering working, but it would be preferable to move the joins into my custom model collection instantiation, so this custom column is always accessible when using my model.

It may also make sense to add a function in my model collection that specifically loads the contents of the joins, but is separate from instantiation. This may lower the overhead in times when I'm interacting with my model but do not need the extra column.

I'm looking for a suggestion as to which of the latter two solutions is a better one, and a way to implement it, or if this cannot be provided, a way to get filtering working when my joins are within the grid.

Thank you, help appreciated!

protected function _prepareCollection()
{
    $collection = Mage::getModel('mymodel/post')
        ->getCollection()
        ->addFieldToFilter( 'post_type', array('eq' => 'post') );

    // Join to additional wordpress tables so we have all the data we need
    $collection
        ->getSelect()
        ->join(
            'tag_relationships',                                                                                      // Alias
            'id = tag_relationships.object_id',                                                                       // On clause
            array('tag_ids' => 'tag_relationships.tag_id')                                                 // Column
        );

    $collection->getSelect()->join(
        'tags',                                                                                                   // Alias
        'tags.tag_id = tag_relationships.tag_id',
        array('tags' => new Zend_Db_Expr('group_concat(`tags`.name SEPARATOR ", ")') )  // Group concat
    );


    $collection->getSelect()->group('main_table.id');


    $this->setCollection($collection);
    parent::_prepareCollection();
    return $this;
}

protected function _prepareColumns()
{

    // Save the ID of the product we're editing
    $productId = Mage::app()->getRequest()->getParam('id');
    $map = Mage::getModel('mymodel/post')->load($productId);

    $helper = Mage::helper('company_mymodel');
    $currency = (string) Mage::getStoreConfig(Mage_Directory_Model_Currency::XML_PATH_CURRENCY_BASE);

    $this->addColumn('itemCheckbox', array(
        'index'      => 'ID',
        'type'       => 'checkbox',
        'width'      => 20,
        'sortable'   => false,
        'field_name' => 'map[]',
        'values'     => $map->getRelatedProjects($productId)
    ));

    $this->addColumn('id', array(
        'header' => $helper->__('ID'),
        'index'  => 'ID'
    ));


    $this->addColumn('tags', array(
        'header' => $helper->__('Terms'),
        'index'  => 'tags',
        'filter_index' => 'tags',
        'filter_condition_callback' => array($this, 'tagsFilter')
    ));


    $this->addExportType('*/*/exportRelatedCsv', $helper->__('CSV'));
    $this->addExportType('*/*/exportRelatedXml', $helper->__('XML'));

    return parent::_prepareColumns();
}

Best Answer

I recommend to use Magento methods over Zend_db_Select methods, because magento is doing book keeping, what is joined and which fields are available.

Beside this, if it is not just joined, you need to define either a filter_index or the filter callback you seem to have