6

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:

4
  • 3
    return $a['brand_order'] <=> $b['brand_order'] ?: $a['title'] <=> $b['title'] – What you're doing isn't guaranteed to work, since sorts aren't guaranteed to be stable. Commented Mar 5, 2019 at 13:38
  • @deceze this question was specific about php7 and the spaceship operator, I think this hasn't been explicit answered in the other answers... Commented Mar 5, 2019 at 14:27
  • The spaceship operator doesn't make this question unique. The unique part is the comparison by two separate conditions. And in fact, both topics are discussed in the duplicate. Perhaps not in exactly this combination, but certainly close enough that you can assemble the information into code that fits specifically your situation. Commented Mar 5, 2019 at 14:29
  • 1
    blog.martinhujer.cz/… Commented Oct 10, 2020 at 21:51

1 Answer 1

11
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

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, that's what I was looking for. And now where I read your code, its pretty logically too.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.