I have this array that needs sorting alphabetically, ignoring accents (as in "e" should be right before "é", and "a" should be followed by its variants, such as "à", for example). The array is read from a JSON file, decoded, is organized(or should be), then encoded back (for employees to add objects). My only problem is every letter that has an accent is placed at the end. Here's an example of my code :
$myArray = [
{"myKey":"Aaa","values":[1,1,1,1,1,1,1]},
{"myKey":"Test01","values":[1,1,1,1,1,1,1]},
{"myKey":"Test02","values":[1,1,1,1,1,1,1]},
{"myKey":"BBB","values":[1,1,1,1,1,1,1]},
{"myKey":"Écha","values":[1,1,1,1,1,1,1]}
]
setlocale(LC_COLLATE, 'fr_CA.utf8');
usort($myArray, function($a, $b){
return strcoll($a["myKey"], $b["myKey"]);
});
$myNewFile = json_encode($myArray,JSON_NUMERIC_CHECK|JSON_UNESCAPED_UNICODE);
echo $myNewFile;
The echo gives :
[
{"myKey":"Aaa","values":[1,1,1,1,1,1,1]},
{"myKey":"BBB","values":[1,1,1,1,1,1,1]},
{"myKey":"Test01","values":[1,1,1,1,1,1,1]},
{"myKey":"Test02","values":[1,1,1,1,1,1,1]},
{"myKey":"Écha","values":[1,1,1,1,1,1,1]}
]
When it should be :
[
{"myKey":"Aaa","values":[1,1,1,1,1,1,1]},
{"myKey":"BBB","values":[1,1,1,1,1,1,1]},
{"myKey":"Écha","values":[1,1,1,1,1,1,1]},
{"myKey":"Test01","values":[1,1,1,1,1,1,1]},
{"myKey":"Test02","values":[1,1,1,1,1,1,1]}
]
I've also tried the following, as I tried my best to find an existing solution with the multiple posts on this subject:
$collator = new Collator('fr_CA.utf8');
$collator->sort($myArray);
and (not necessary since I'm on PHP 7+, but I'm desperate)
usort($myArray["Ingrédients"], 'custom_sort');
function custom_sort(($a, $b){
return strcoll($a["Ingrédients"], $b["Ingrédients"]);
});
and (since I'm on PHP 7+)
usort($myArray, function($a, $b) {
return $a['myKey'] <=> $b['myKey'];
});
I've also used different country codes for my setlocale, such as
'fr_CA.utf8', 'fr_FR.utf8', 'fr_CA', 'fr_FR'
Each one of these methods seem to work for everyone in all the posts I've seen so far, but they're quite dated. They all work, apart from sorting accents, so I get the same result I'm getting, no matter the method. The server is on PHP 7.1.1 if that helps.
Ok, so in short, the problem you have is due to the value of the character. strcoll
compares strings based on the values of their characters for the character set you are using. I am going to assume you are using utf-8 or something very similar. See UTF-8 for the values, notice how the value of e with an accent mark is much higher than Z? That is why you are having this problem. In order to fix it, you will have to add special cases for the accented characters, as the normal sort with not work otherwise. So, basically, create your own compare function which would put e with an accent mark where f would usually be and so on.