Kaleb Thompson
Kaleb Thompson

Reputation: 113

Ordering output of php array into elements

I have been stuck with this problem for many days now, but cannot get anything to work. I have found many conflicting posts on SO about using various methods which are much slower in php7 and there are newer, better methods to use. My target server is php 7, so that is OK.

Here is the issue I have:

object(SingleClass)#463 (8) {
  ["id"]=>
  string(1) "1"
  [created_date]=>
  string(19) "2020-06-25 17:50:00"
  [cricket]=>
  string(27) "{"data":{"example":"data"}}"
  [rugby]=>
  string(27) "{"data":{"example":"data"}}"
  [football]=>
  string(27) "{"data":{"example":"data"}}"
  [tennis]=>
  string(27) "{"data":{"example":"data"}}"
  [swimming]=>
  string(27) "{"data":{"example":"data"}}"
  [order]=>
  string(60) "{"cricket":1,"football":2,"rugby":3,"swimming":4,"tennis":5}"
}

In my view, I have access to this object. I need to order the output of each of the above depending on the [order] array values and then print the object. So in this example, the output can ignore some - like id and created_date - but should be something like:

 echo `cricket` data
 echo `football` data
 echo `rugby` data
 echo `swimming` data
 echo `tennis` data

The output above is a print_r of the $this->singleitem, so I can access each object like this:

<?php $orders = json_decode($this->singleitem->order);?>
<?php foreach ($orders as $itemOrder) {
    print_r($itemOrder);
} ?>

Which gives me 12345 with a print_r on $this->singleitem->order I get:

stdClass Object ( [cricket] => 1 [football] => 2 [rugby] => 3 [swimming] => 4 [tennis] => 5 )

If the [order] is empty, or a value is missing, it should skip the corresponding missing item and append it to the end, is this even possible in php?

Thanks!

Upvotes: 1

Views: 51

Answers (2)

bumperbox
bumperbox

Reputation: 10214

This proabably won't work exactly as expected, because the data structure i have used, might be slightly different, but it should give you a good idea of how to do it.

<?php
$singleitem = '
{
  "id": 1,
  "created_date": "2020-06-25 17:50:00",
  "cricket": {
    "data": {
      "example": "data"
    }
  },
  "rugby": {
    "data": {
      "example": "data"
    }
  },
  "football": {
    "data": {
      "example": "data"
    }
  },
  "tennis": {
    "data": {
      "example": "data"
    }
  },
  "swimming": {
    "data": {
      "example": "data"
    }
  },
  "order": {
    "cricket": 1,
    "rugby": 3,
    "swimming": 4,
    "tennis": 5
  }
}
';

$json = json_decode($singleitem, true); // true turns the data into an assoc array
    
$sport_order = array_keys($json['order']);

// list all sport data in order
foreach ($sport_order as $sport) {
    echo $sport .  json_encode($json[$sport]['data']) . "<br>";
}

// list all sport data, that is not in sort list, last
// eg in this example football should be listed last
foreach ($json as $key => $val) {
    
    // idealy we should have a list of valid values, rather then excluding id, order and created_date,
    // unless we are sure there will never be any further meta data added
    
    // ignore id
    if ($key === 'id') {
        continue;
    }

    // ignore order
    if ($key === 'order') {
        continue;
    }

    // ignore created_date
    if ($key === 'created_date') {
        continue;
    }

    if (in_array($key, $sport_order)) {
        continue;
    }

    echo $key .  json_encode($val) . "<br>";
}

Upvotes: 1

Phil
Phil

Reputation: 164760

  1. Get the order as an array and sort by the number value (just in case they aren't always in order already)
  2. Iterate the keys of the sorted order array and output the corresponding property from singleitem
$order = json_decode($this->singleitem->order, true); // "true" to produce an assoc array
asort($order); // sort by value, maintaining keys

foreach(array_keys($order) as $prop) {
  $val = json_decode($this->singleitem->$prop);
  echo $val->data->example, PHP_EOL;
}

Demo ~ https://3v4l.org/XCcj5

Upvotes: 1

Related Questions