Search code examples
phplaravelsortingcollections

How do I sort a Laravel Collection by multiple properties with both asc and desc?


If I have an Illuminate\Support\Collection, how do I sort by multiple properties with both asc and desc? (This is a simple hypothetical - not at all looking for tips on query building.)

$collection = User::all(); // not looking for User::orderBy()->get() solutions.  Read the question.
$sorting_insructions = [
    ['column'=>'first_name', 'order'=>'asc'],
    ['column'=>'date_of_birth', 'order'=>'desc'],
];
$collection->sort(function($a,$b) use ($sorting_instructions){
    // something...
});

Solution

  • Whoever uses this, just keep in mind - you'll need to tweak it depending if your using collection of objects or associative arrays. Should be an easy tweak. Just change the $a[]/$b[] stuff to $a-> and $b->

        public static function multiPropertySort(Collection $collection, array $sorting_instructions){
    
            return $collection->sort(function ($a, $b) use ($sorting_instructions){
    
                //stuff starts here to answer question...
    
                foreach($sorting_instructions as $sorting_instruction){
    
                    $a[$sorting_instruction['column']] = (isset($a[$sorting_instruction['column']])) ? $a[$sorting_instruction['column']] : '';
                    $b[$sorting_instruction['column']] = (isset($b[$sorting_instruction['column']])) ? $b[$sorting_instruction['column']] : '';
    
                    if(empty($sorting_instruction['order']) or strtolower($sorting_instruction['order']) == 'asc'){
                        $x = ($a[$sorting_instruction['column']] <=> $b[$sorting_instruction['column']]);
                    }else{
                        $x = ($b[$sorting_instruction['column']] <=> $a[$sorting_instruction['column']]);
    
                    }
    
                    if($x != 0){
                        return $x;
                    }
    
                }
    
                return 0;
    
            })->values();
        }