skip to Main Content

I’m trying to use usort on an array, and get a different behavior regarding the version of PHP:

$arr1 = [
    [
        'points' => 10,
        'date' => 3,
    ],
    [
        'points' => 10,
        'date' => 2,
    ],
    [
        'points' => 10,
        'date' => 1,
    ]
];

usort($arr1, function ($a, $b) {
    if($a['points'] == $b['points']){
      return 0;
    }
    return ($a['points'] < $b['points']) ? 1 : -1;
});

This array contains a “date” value, and is ordered DESC on this value, after the usort based on a “points” value, items with the same “points” value are reversed on PHP 5.6, and keep their original order on PHP 7.0…

You may test this online here, with the different PHP versions (please test against PHP 5.6.29 and 7.0.1): http://sandbox.onlinephpfunctions.com/code/2715220539623b4b699ebb3f90a4b01c98eef53d

How could I get the same sorting behavior on equal points under any PHP version?

3

Answers


  1. If you want to have the same results in both versions, you will need to ensure that you specify how equal items will deal with other fields.

    So you could solve this with…

    usort($arr1, function ($a, $b) {
        if($a['points'] == $b['points']){
          return $a['date'] - $b['date'];
        }
        return ($a['points'] < $b['points']) ? 1 : -1;
    });
    

    So if the points value is the same, then use date as the differentiator (assuming a numeric comparison would work.)

    Login or Signup to reply.
  2.     $array = [
            ['points' => 10, 'date' => 3],
            ['points' => 10, 'date' => 2],
            ['points' => 10, 'date' => 1],
        ];
    
        usort($array, function ($a, $b) {
            if($a['points'] === $b['points']){
                return $b['date'] <=> $a['date'];
            }
            return $a['points'] <=> $b['points'];
        });
    
        var_dump($array);
    
    Login or Signup to reply.
  3. As others have already noted, you need to sort on more than one key. PHP provides for this through its compare_func callable, and it also provides the <=> *(“spaceship”) operator for your convenience in writing such functions.

    If your compare_func finds that points is equal, it should proceed to compare date and so on, returning the first value that isn’t zero. (You can use the or operator to do this.)

    And, if all of the sort-keys are equal, the behavior of usort() is “unpredictable.” In this case, you should not presume that the records will be presented in any particular order … even from one call to usort() to the next. If you think that “this version of PHP ‘always’ does it this way, and that version ‘always’ does it some other way,” assume that you are merely mistaken.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search