<?php
// Relatively small array of various file types.
// I want to display the results of the files array in this order.
$sort_array = array('mp4','mpeg','flv','f4v','avi'); 
$weights = array_flip($sort_array);
// This is the array I would like to sort on filetype. The data is coming from Amazon simple DB... 
// and again a given media object will only have a small handful of files... in fact 
// probably no more than two or three.
$files = array(
	array('title'=>'race day','filetype'=>'f4v','filename'=>'racing.f4v'),
	array('title'=>'playin checkers','filetype'=>'mp4','filename'=>'checkers.mp4'),
	array('title'=>'playin checkers','filetype'=>'mp3','filename'=>'checkers.mp3'),
	array('title'=>'playin checkers','filetype'=>'avi','filename'=>'checkers.avi'),
	array('title'=>'eating melons','filetype'=>'mp4','filename'=>'watermelon.mp4'),
	array('title'=>'eating melons (audio)','filetype'=>'mp3','filename'=>'watermelon.mp3')
);
usort($files, make_comparer(['filetype', SORT_ASC, function($t) use ($weights) { return $weights[$t]; }]));

print_r($files);



function make_comparer() {
    // Normalize criteria up front so that the comparer finds everything tidy
    $criteria = func_get_args();
    foreach ($criteria as $index => $criterion) {
        $criteria[$index] = is_array($criterion)
            ? array_pad($criterion, 3, null)
            : array($criterion, SORT_ASC, null);
    }

    return function($first, $second) use (&$criteria) {
        foreach ($criteria as $criterion) {
            // How will we compare this round?
            list($column, $sortOrder, $projection) = $criterion;
            $sortOrder = $sortOrder === SORT_DESC ? -1 : 1;

            // If a projection was defined project the values now
            if ($projection) {
                $lhs = call_user_func($projection, $first[$column]);
                $rhs = call_user_func($projection, $second[$column]);
            }
            else {
                $lhs = $first[$column];
                $rhs = $second[$column];
            }

            // Do the actual comparison; do not return if equal
            if ($lhs < $rhs) {
                return -1 * $sortOrder;
            }
            else if ($lhs > $rhs) {
                return 1 * $sortOrder;
            }
        }

        return 0; // tiebreakers exhausted, so $first == $second
    };
}
