The problem with using several usort() calls in a row is that subsequent sorts do not respect the order imposed by previous sorts. To use the technical term: the Quicksort algorithm (which usort() implements) is not stable.
What that means is that there is no guaranteed that any two elements that are equal (as far as the function usort() is using is concerned) will come out in the same order that they went in. For example, if you had
name wins losses
Redsox 3 9
Reds 8 1
Rangers 11 1
Whitesox 8 5
And you sorted by Wins, you could get either
name wins losses
Redsox 3 9
Whitesox 8 5
Reds 8 1
Rangers 11 1
or
name wins losses
Redsox 3 9
Reds 8 1
Whitesox 8 5
Rangers 11 1
(Because if you only look at wins, Reds and Whitesox are equal); and if you then sorted either of those by losses you'd get either
name wins losses
Reds 8 1
Rangers 11 1
Whitesox 8 5
Redsox 3 9
or
name wins losses
Rangers 11 1
Reds 8 1
Whitesox 8 5
Redsox 3 9
(because, looking only at losses, Rangers and Reds are equal).
There is no real way of predicting the output order of effectively equal elements - at least, not without doing so much analysis that you might as well be doing the sorting yourself - but in the tradeoff between performance and stability, performance wins.
The reason for that (and I'm finally getting to the solution) is because you can get all of the sorting done in one usort() call by doing all of the comparisons in a single function:
First, look at the most important field of the two elements (wins, in this case).
If they're different, you have your answer about which one should be before the other.
If they're the same, look at the next most important field (losses) and see if they differ. If they do you have your answer.
If the wins and losses were both the same, you break the tie by looking at the third field.
It's like sorting names: "Apthorp" comes before "Blofield" because 'A' comes before 'B', but "Aligheri" comes before "Arkwright" because 'l' comes before 'r'.
function compare_wins($x, $y)
{
return $x['wins'] - $y['wins'];
}
function compare_losses($x, $y)
{
return $x['losses'] - $y['losses'];
}
function compare_ties($x, $y)
{
return $x['ties'] - $y['ties'];
}
function compare($x, $y)
{
$wins = compare_wins($x, $y);
if($wins) return $wins;
$losses = compare_losses($x, $y);
if($losses) return -$losses; // Descending
$ties = compare_ties($x, $y);
if($ties) return $ties;
return 0;
}
(Incidentally, you have a bug in your comparelosses() test.)