【PHP】多次元の連想配列を値でソートするコードを作ってみた

【PHP】多次元の連想配列を値でソートするコードを作ってみたWeb開発者の備忘録多次元の連想配列を値でソートしたい場合、なかなか期待値通りにならないのが多いので、自分で作りました。
※http://php.net/manual/ja/function.array-multisort.php
 User Contributed Notesに記載のarray_msort()がその例(PHP5.3以上対応版も同様にNG)


class multisort {
	static $orderby; // array( KEYNAME => array('order'=>SORT_ASC/SORT_DESC , 'flags'=>SORT_NUMERIC/SORT_STRING)
	static function callback_function($a,$b) {
		// ORDERBY で指定されたカラム順に大小比較を行う。
		// 大小比較出来た時点でこの関数は抜け出すが、同値と判断された場合は、次のカラムで大小比較するようにしている
		foreach ( self::$orderby as $keyname => $params ) {
			// 型変換
			if     ( @$params['flags'] == SORT_NUMERIC ) {
				$valueA = floatval(@$a[$keyname]);
				$valueB = floatval(@$b[$keyname]);
			}
			elseif ( @$params['flags'] == SORT_STRING ) {
				$valueA = strval(@$a[$keyname]);
				$valueB = strval(@$b[$keyname]);
			}
			else {
				$valueA = @$a[$keyname];
				$valueB = @$b[$keyname];
			}
			// 並び順
			if ( @$params['order'] == SORT_ASC ) {
				if     ($valueA > $valueB) return  1;
				elseif ($valueA < $valueB) return -1;
			}
			else {
				if     ($valueA > $valueB) return -1;
				elseif ($valueA < $valueB) return  1;
			}
		}
		return 0;
	}
	static function exec($data) {
		$olddata = $data;
		uasort($data, array(self,'callback_function')); // 配列のキーを保持したまま値でソートする
		return $data;
	}
}

$arr1 = array(
    array('id'=>1,'name'=>'aA','cat'=>'cc'),
    array('id'=>2,'name'=>'aa','cat'=>'dd'),
    array('id'=>3,'name'=>'bb','cat'=>'cc'),
    array('id'=>4,'name'=>'bb','cat'=>'dd')
);

multisort::$orderby = array(
	'name' => array('order'=>SORT_ASC , 'flags'=>SORT_STRING),
	'cat'  => array('order'=>SORT_DESC) // flags省略
);
$arr2 = multisort::exec($arr1);

header('Content-type: text/plain');
var_dump($arr1);
var_dump($arr2);

結果は以下(そのままだと分かり辛いので表現は変えています)


$arr1 = array(
    array('id'=>1,'name'=>'aA','cat'=>'cc'),
    array('id'=>2,'name'=>'aa','cat'=>'dd'),
    array('id'=>3,'name'=>'bb','cat'=>'cc'),
    array('id'=>4,'name'=>'bb','cat'=>'dd'),
);
$arr2 = array(
    array('id'=>1,'name'=>'aA','cat'=>'cc'),
    array('id'=>2,'name'=>'aa','cat'=>'dd'),
    array('id'=>4,'name'=>'bb','cat'=>'dd'),
    array('id'=>3,'name'=>'bb','cat'=>'cc'),
);

flags指定が不十分ですが、うまく拡張していけば、大文字小文字を意識しない、とかロケールを意識したものとか、もっと応用が利くと思います。