I have an associate array like this:
$all_works = [
["title"=>"A Children’s Story", "year"=>"2024"],
["title"=>"Occurred during the Day", "year"=>"2021"],
["title"=>"Future and Past", "year"=>"2021"],
["title"=>"Future and History", "year"=>"2020"],
["title"=>"Open the School, Close the Studio", "year"=>"2023"],
["title"=>"To Reconstruct, To Rebuild", "year"=>"2024"],
["title"=>"Eyeglasses, a Story", "year"=>"2023"],
["title"=>"Nomadic Life", "year"=>"2024"],
["title"=>"Chipotle!", "year"=>"2022"],
["title"=>"between Art & Technology", "year"=>"2020"],
["title"=>"interview Script", "year"=>"2018"],
["title"=>"memories and confession", "year"=>"2024"],
["title"=>"Guest of Pluto", "year"=>"2022"],
["title"=>"A Prologue", "year"=>"2022"],
["title"=>"You are in this place", "year"=>"2023"],
["title"=>"Happening Now", "year"=>"2024"],
["title"=>"Review Catalogue", "year"=>"2022"],
["title"=>"A living being of Mars", "year"=>"2021"],
];
And I’m trying to sort this array by the numeric order of the “year” values of each sub-array, and when the “year” values are the same, sort the sub-arrays by the natural alphanumeric order of the “title” value.
So this is what I did:
usort($all_works, function($work1, $work2) {
return $work2["year"] <=> $work1["year"];
});
echo "<br><br>";
echo "<pre>";
print_r($all_works);
echo "</pre>";
usort($all_works, function($work3, $work4){
if($work3["year"] == $work4["year"]){
return strnatcmp($work3["title"], $work4["title"]);
}else{
return 0;
}
});
echo "<br><br>";
echo "<pre>";
print_r($all_works);
echo “</pre>";
When I run these code with php 8.2.0, it works totally well as I expected. And the output is:
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[2] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[3] => Array
(
[title] => memories and confession
[year] => 2024
)
[4] => Array
(
[title] => Happening Now
[year] => 2024
)
[5] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[6] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[7] => Array
(
[title] => You are in this place
[year] => 2023
)
[8] => Array
(
[title] => Chipotle!
[year] => 2022
)
[9] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[10] => Array
(
[title] => A Prologue
[year] => 2022
)
[11] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[12] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[13] => Array
(
[title] => Future and Past
[year] => 2021
)
[14] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[15] => Array
(
[title] => Future and History
[year] => 2020
)
[16] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => Happening Now
[year] => 2024
)
[2] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[3] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[4] => Array
(
[title] => memories and confession
[year] => 2024
)
[5] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[6] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[7] => Array
(
[title] => You are in this place
[year] => 2023
)
[8] => Array
(
[title] => A Prologue
[year] => 2022
)
[9] => Array
(
[title] => Chipotle!
[year] => 2022
)
[10] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[11] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[12] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[13] => Array
(
[title] => Future and Past
[year] => 2021
)
[14] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[15] => Array
(
[title] => Future and History
[year] => 2020
)
[16] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
However, when I run the exact same code with php 7.4.33, the result looks very random (especially the array output after the second usort function, not only the alphanumeric order of the “title”s is not working, but also the numeric order of the “year” is messed up). Here is the result:
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => Happening Now
[year] => 2024
)
[2] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[3] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[4] => Array
(
[title] => memories and confession
[year] => 2024
)
[5] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[6] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[7] => Array
(
[title] => You are in this place
[year] => 2023
)
[8] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[9] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[10] => Array
(
[title] => Chipotle!
[year] => 2022
)
[11] => Array
(
[title] => A Prologue
[year] => 2022
)
[12] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[13] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[14] => Array
(
[title] => Future and Past
[year] => 2021
)
[15] => Array
(
[title] => Future and History
[year] => 2020
)
[16] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
Array
(
[0] => Array
(
[title] => A Children’s Story
[year] => 2024
)
[1] => Array
(
[title] => Chipotle!
[year] => 2022
)
[2] => Array
(
[title] => Future and History
[year] => 2020
)
[3] => Array
(
[title] => between Art & Technology
[year] => 2020
)
[4] => Array
(
[title] => A living being of Mars
[year] => 2021
)
[5] => Array
(
[title] => Future and Past
[year] => 2021
)
[6] => Array
(
[title] => Occurred during the Day
[year] => 2021
)
[7] => Array
(
[title] => A Prologue
[year] => 2022
)
[8] => Array
(
[title] => Guest of Pluto
[year] => 2022
)
[9] => Array
(
[title] => Review Catalogue
[year] => 2022
)
[10] => Array
(
[title] => Happening Now
[year] => 2024
)
[11] => Array
(
[title] => Eyeglasses, a Story
[year] => 2023
)
[12] => Array
(
[title] => Open the School, Close the Studio
[year] => 2023
)
[13] => Array
(
[title] => You are in this place
[year] => 2023
)
[14] => Array
(
[title] => Nomadic Life
[year] => 2024
)
[15] => Array
(
[title] => To Reconstruct, To Rebuild
[year] => 2024
)
[16] => Array
(
[title] => memories and confession
[year] => 2024
)
[17] => Array
(
[title] => interview Script
[year] => 2018
)
)
I’m not sure what is going on, and can’t even find any logic or pattern in this result from php 7.4.33.
Does usort() behave differently in php 8.2.0 vs php 7.4.33?
What is php 7.4.33 doing here exactly in this example cause the second result that looks totally non-logical? (Or there is a logic but I didn’t see?)
What should I do to make my code work as how it works in php 8.2.0 while using php 7.4.33?
(additional information: I was running my code using MAMP local server on mac, if that matters).
2
Answers
From the manual:
Your problem is that the second sort isn’t "stable" with regard to the elements that compare as equal.
To fix this, just move the sorting logic into a single function and sort only once:
As previously mentioned, PHP8 implemented stable sorting and any versions before that made no promises about preserving the original element order.
As for cleaning up your code, it can be reduced to the following: (Demo)
The equivalent behavior can be enjoyed with
array_multisort()
as well: (Demo)