Search code examples
phparrayssortingphp-7usort

How to usort an array by two parameters using spaceship operator with PHP >=7.0


Is there a more compact way to sort an array by two parameters/fields with PHP ≥7.0 (using the spaceship operator <=>) ?

Right now I just to the trick to sort is first by the second parameter and then by the first:

// Sort by second parameter title
usort($products, function ($a, $b) {
    return $a['title'] <=> $b['title']; // string
});

// Sort by first parameter brand_order
usort($products, function ($a, $b) {
    return $a['brand_order'] <=> $b['brand_order']; // numeric
});

This gives me the result I want; the products a first ordered by brand and then by their title.

I just wonder if there is a way to do it one usort call.


Here is my question as code snippet. This example can be tested here.

<pre><?php
        
<!-- Example array -->
$products = array();

$products[] = array("title" => "Title A",  
              "brand_name" => "Brand B",
              "brand_order" => 1);
$products[] = array("title" => "Title C",  
              "brand_name" => "Brand A",
              "brand_order" => 0);
$products[] = array("title" => "Title E",  
              "brand_name" => "Brand A",
              "brand_order" => 0);
$products[] = array("title" => "Title D",  
              "brand_name" => "Brand B",
              "brand_order" => 1);

// Sort by second parameter title
usort($products, function ($a, $b) {
    return $a['title'] <=> $b['title']; // string
});

// Sort by first parameter brand_order
usort($products, function ($a, $b) {
    return $a['brand_order'] <=> $b['brand_order']; // numeric
});

// Output
foreach( $products as $value ){
    echo $value['brand_name']." — ".$value['title']."\n";
}

?></pre>


Similar question but not specific about php7 and the spaceship operator have been answered here:


Solution

  • usort($products, function ($a, $b) {
        if ( $a['brand_order'] == $b['brand_order'] ) {  //brand_order are same
           return $a['title'] <=> $b['title']; //sort by title
        }
        return $a['brand_order'] <=> $b['brand_order']; //else sort by brand_order
    });
    

    Test here