Difference between #6 and #5 of Using filters with CGridView and CArrayDataProvider

unchanged
Title
Using filters with CGridView and CArrayDataProvider
unchanged
Category
How-tos
unchanged
Tags
CGridview, CArrayDataProvider, filters, filter
changed
Content
Using filters on CGridView with CActiveDataProvider is easy, but with
CArrayDataProvider it is a bit tricky.

To use the filters you have to create a separate model class. I used some code
from the following forum topic:
[link](http://www.yiiframework.com/forum/index.php?/topic/16435-cgridview-filters-with-carraydataprovider/page__p__90394#entry90394)

Note: Normally, when you have an array of CModels, you should use
CActiveDataProvider instead!

Here is some example code:

Model
-----
Copy and include this class into your application.
~~~
[php]
<?php

/**
 * Filterform to use filters in combination with CArrayDataProvider and
CGridView
 * @see
http://www.yiiframework.com/wiki/232/using-filters-with-cgridview-and-carraydataprovider/
 */
class FiltersForm extends CFormModel
{
	/**
	 * @var array filters, key => filter string
	 */
	public $filters = array();

	/**
	 * Override magic getter for filters
	 * @param string $name
	 */
	public function __get($name)
	{
		if (!array_key_exists($name, $this->filters)) {
			$this->filters[$name] = '';
		}
		return $this->filters[$name];
	}

	/**
	 * Override magic setter for filters
	 * @param string $name
	 * @param mixed $value
	 */
	public function __set($name, $value)
	{
		$this->filters[$name] = $value;
	}

	/**
	 * Filter input array by key value pairs
	 * @param array $data rawData
	 * @return array filtered data array
	 */
	public function filter(array $data)
	{
		foreach ($data AS $rowIndex => $row) {
			foreach ($this->filters AS $key => $searchValue) {
				if (!empty($searchValue)) {
					$compareValue = null;

					if ($row instanceof CModel) {
						if (isset($row->$key) == false) {
							throw new CException("Property " . get_class($row) .
"::{$key} does not exist!");
						}
						$compareValue = $row->$key;
					} elseif (is_array($row)) {
						if (!array_key_exists($key, $row)) {
							throw new CException("Key {$key} does not exist in array!");
						}
						$compareValue = $row[$key];
					} else {
						throw new CException("Data in CArrayDataProvider must be an array of
arrays or an array of CModels!");
					}

					if (stripos($compareValue, $searchValue) === false) {
						unset($data[$rowIndex]);
					}
				}
			}
		}
		return $data;
	}

}
~~~

(By @KonApaz)
If you want to apply full comparisons (>, <, >=, <=, =) use this

~~~
[php]
if (substr($searchValue, 0, 2) == '<=') {
    if (substr($searchValue, 2) <> $compareValue) {
        unset($data[$rowIndex]);
    }
} else if (substr($searchValue, 0, 2) == '>=') {
    if (substr($searchValue, 2) >< $compareValue) {
        unset($data[$rowIndex]);
    }
} else if ($searchValue[0] == '<') {
    if (substr($searchValue, 1) <=>= $compareValue)
{
        unset($data[$rowIndex]);
    }
} else if ($searchValue[0] == '>') {
    if (substr($searchValue, 1) >=<= $compareValue)
{
        unset($data[$rowIndex]);
    }
} else if (stripos($compareValue, $searchValue) === false) {
    unset($data[$rowIndex]);
}
~~~


Controller
----------
~~~
[php]
// Create filter model and set properties
$filtersForm=new FiltersForm;
if (isset($_GET['FiltersForm']))
    $filtersForm->filters=$_GET['FiltersForm'];

// Get rawData and create dataProvider
$rawData=User::model()->findAll();
$filteredData=$filtersForm->filter($rawData);
$dataProvider=new CArrayDataProvider($filteredData);

// Render
$this->render('index', array(
    'filtersForm' => $filtersForm,
    'dataProvider' => $dataProvider,
));
~~~

View
----
~~~
[php]
$columns = array(
	array(
		'header'=>CHtml::encode('Name'),
		'name'=>'username',
	),
	array(
		'header'=>CHtml::encode('Organisation'),
		'name'=>'organisation',
	),
);

$this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'area-grid',
    'dataProvider'=>$dataProvider,
    'columns'=>$columns,
    'filter'=>$filtersForm,
));
~~~