0

I need a bit of help ordering a SimpleXML array in an alphabetical order using one of it's attribute ($url). I have the following code that generate a page:

<?php
$xml = simplexml_load_file($xml_url);
$ids = array();

foreach($xml->list as $id) {
   $ids[] = $id;
}

//It works but randomize instead of sorting alphabetically
usort($ids, function ($a, $b) {
   return strnatcmp($a['url'], $b['url']);
});

foreach ($ids as $id) {
   PopulatePage($id);
}

function PopulatePage($id) {
   $url = $id->url;
   $img = $id->img;
   //OTHER CODES TO GENERATE THE PAGE
}?>

QUESTION RESOLVED!

  • Can you show the code you tried which gave an error? `$ids` is a normal PHP array, so sorting it should be easy, and shouldn't change anything about the items inside it. – IMSoP May 01 '22 at 10:13
  • I can't order a SimpleXMLObject array, or at least I'm not able to. I've tried converting it to a "normal" array, but since "$xml->list as $id" is no more valid in the converted array, it stops working... – ThePlayer96 May 01 '22 at 10:37
  • There's no conversion necessary beyond what you've already done to build the $ids array, and nothing special about sorting an array of SimpleXMLElement objects, you can just use `usort` as you would for any other custom sort. If you're not familiar with how that function works, see the linked reference. – IMSoP May 01 '22 at 10:49
  • I've tried using `usort` (I've updated the code above) and it works, but it doesn't order it in the correct way, only randomized... – ThePlayer96 May 01 '22 at 11:49
  • Your images don't really demonstrate anything, because I've no idea what the correct order would look like; but it doesn't matter, because I can see exactly what's happening, and have written an answer explaining. – IMSoP May 01 '22 at 12:10

1 Answers1

0

There is no conversion needed, you already have an array which you can sort, you just need to understand how usort callbacks work. Each of the items in your $ids array is a SimpleXMLElement object, and each time your callback is run, it will be given two of those objects to compare. Those objects will be exactly the same as in the existing PopulatePage function, so accessing the URL needs to happen exactly as it does there ($url = $id->url;) not using a different notation ($id['url']).

To make it more explicit, let's write a named function with lots of clear variable names:

function CompareTwoIds(SimpleXMLElement $left_id, SimpleXMLElement $right_id): int {
    $left_url = $left_id->url;
    $right_url = $right_id->url;
    return strncatcmp($left_url, $right_url);
}

Now you can test calling that function manually, and use it as the callback when you're happy:

usort($ids, 'CompareTwoIds');

Once you're comfortable with the principles, you may decide to skip the extra verbosity and just write this, which is completely equivalent:

usort($ids, fn($a,$b) => strncatcmp($a->url, $b->url));
IMSoP
  • 89,526
  • 13
  • 117
  • 169