1

I'm back to this good old problem where using a Varien_Data_Collection in a grid does not handle sorting, paging nor filtering.

I've found some useful resources such as :

The first one is incomplete whereas the answer in the second one is too broad to help.

I know I have to use a custom collection class that extends Varien_Data_Collection I simply wanna know exactly the methods (and the details of them) I need to implement inside to be able to handle paging, sorting and filtering ?

1 Answer 1

5

After several tests I managed to get it right.

Here's the collection class that extends Varien_Data_Collection and that handles paging / filtering / sorting so it can be used in admin grids.

<?php

class DigitalPianism_Module_Model_Report extends Varien_Data_Collection {

    public function loadData($printQuery = false, $logQuery = false)
    {
        if ($this->isLoaded()) {
            return $this;
        }

        // We add the renders
        $this->_renderFilters()
            ->_renderOrders()
            ->_renderLimit();

        $this->_setIsLoaded();
    }

    public function addFieldToFilter($field, $condition = null)
    {
        $keyFilter = key($condition);
        $valueFilter = (string)$condition[$keyFilter];
        $this->addFilter($field, $valueFilter);
        return $this;
    }

    protected function _renderFilters()
    {
        // If elements are already filtered, return this
        if ($this->_isFiltersRendered) {
            return $this;
        }

        // Loop the collection
        foreach($this->_items AS $key => $item) {

            foreach($this->_filters AS $filter) {

                $keyFilter = $filter->getData()['field'];
                $valueFilter = $filter->getData()['value'];
                //$condFilter = $filter->getData()['type']; // not used in this example
                if (strpos($valueFilter, "%") !== false) {
                    // Delete "'%" and "%'" from the string
                    $valueFilter = substr($filter->getData()['value'], 2, -2);
                }

                // Item value
                $itemValue = $item->getData($keyFilter);

                // If it's not an array, we use the search term to compare with the value of our item
                if (!is_array($itemValue)) {
                    if (strpos(strtolower($itemValue), strtolower($valueFilter)) === FALSE) {
                        unset($this->_items[$key]);
                        // If search term not found, unset the item to not display it!
                    }
                } else {
                    // If it's an array
                    $found = false;
                    foreach ($itemValue AS $value) {
                        if (strpos(strtolower($value), strtolower($valueFilter)) !== FALSE) {
                            $found = true;
                        }
                    }
                    if (!$found) {
                        unset($this->_items[$key]); // Not founded in the array, so unset the item
                    }
                }
            }
        }

        $this->_isFiltersRendered = true;
        return $this;
    }

    protected function _renderOrders()
    {
        $keySort = key($this->_orders);
        $keyDirection = $this->_orders[$keySort];
        // We sort our items tab with a custom function AT THE BOTTOM OF THIS CODE
        usort($this->_items, $this->_build_sorter($keySort,$keyDirection));
        return $this;
    }

    protected function _renderLimit()
    {
        $this->_totalRecords = sizeof($this->_items);

        if($this->_pageSize){
            $this->_items = array_slice($this->_items, ($this->_curPage - 1) * $this->_pageSize, $this->_pageSize);
        }
        return $this;
    }

    protected function _build_sorter($key,$direction)
    {
        return function ($a, $b) use ($key,$direction) {
            if ($direction == self::SORT_ORDER_ASC)
                return strnatcmp($a[$key], $b[$key]); // Natural comparaison of string
            else
                return -1 * strnatcmp($a[$key], $b[$key]); // reverse the result if sort order desc !
        };
    }

}

Feel free to let me know if you find a bug or something missing

3
  • 1
    What does $itemValue = $item->getGeneric($keyFilter); do that $itemValue = $item->getData($keyFilter); or $itemValue = $item->getDataUsingMethod($keyFilter); will not? Commented Jul 5, 2016 at 14:48
  • @LeeSaferite nothing at all I got right of that bit, I kept it originally from the first link of my question but didn't even bother testing its purpose ^^ Commented Jul 5, 2016 at 14:55
  • I created this model, still the filter is not working. Can you please help out? Commented Apr 27, 2017 at 9:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.