Yii CArrayDataProvider add case-sensitive option

In Yii if you use CArrayDataProvider for a data set, it will use PHP’s array_multisort for sorting, which is normally case sensitive so if you have any items that aren’t capitalized, it will mess up the order and is inconsistent with how MySql sorts.

And now that I realize this extra sorting step is happening (and it certainly makes sense to do it that way, Yii doesn’t know where my data originally came from) — I may re-think where I’m using this to see if it can be done via a database (CActiveDataProvider) search since I’m usually fetching the data from the db anyway and it would be more efficient to have MySql sort it at the time it’s requested.

In any case – if for whatever reason you are not using a db connection for the data or really do have to do some pre-processing before handing off to CArrayDataProvider, here is how you can add a case-sensitive switch:

Click here to view code

Override CArrayDataProvider to provide a custom sortData method and add an additional property to toggle the custom bit:

class myCArrayDataProvider extends CArrayDataProvider {
	public $casei = false;
 
	protected function sortData($directions)
	{
		if(empty($directions))
			return;
		$args=array();
		$dummy=array();
		foreach($directions as $name=>$descending)
		{
			$column=array();
			foreach($this->rawData as $index=>$data)
				$column[$index]=is_object($data) ? $data->$name : $data[$name];
			$args[]=&$column;
			$dummy[]=&$column;
			unset($column);
			$direction=$descending ? SORT_DESC : SORT_ASC;
			$args[]=&$direction;
			$dummy[]=&$direction;
			unset($direction);
		}
 
		if ($this->casei) { 
			for ($i = 0; $i < count($args); $i++) {
				$args[$i] = (is_array($args[$i])) ? 
                                          array_map('strtolower', $args[$i]) : $args[$i];
			}
		}
 
		$args[]=&$this->rawData;
		call_user_func_array('array_multisort', $args);
	}
}

Then when creating your dataProvider:

$dataProvider = new myCArrayDataProvider($proj_result, array(
  [rest of your params...]
));
$dataProvider->casei = true;

If you always wanted it case insensitive you could leave out the "casei" param.

Leave a Reply