1

I have an objectlist:

$deliveryOptions = 
 Array ( [0] => stdClass Object ( [item_id] => 55 [value] => delivery-online ) 
        [1] => stdClass Object ( [item_id] => 55 [value] => delivery-campus ) 
        [2] => stdClass Object ( [item_id] => 56 [value] => delivery-campus ) 
        [3] => stdClass Object ( [item_id] => 81 [value] => delivery-blended ) 
       )

I need to format it to an array:

$combined =
( [item_id] => 55 [course-delivery] => array( "delivery-online","delivery-campus")
( [item_id] => 56 [course-delivery] => delivery-campus )
( [item_id] => 81 [course-delivery] => delivery-blended )

My code so far:

foreach ($deliveryOptions as $row)
{  
    $temp = array('item_id'=>$row->item_id,                  
                   'course-delivery'=>$row->value
                    );        
    $course[] = $temp;  
}

foreach ($course as $row)
{    
  $match = array_search($row['item_id'], array_column($combined, 'item_id'));
   
  if(is_numeric($match))
  {
     $combined[$match]['course-delivery'][] = $row['course-delivery'];       
  }
  else{
    array_push($combined, [
        'item_id' => $row['item_id'],
        'course-delivery' => array($row['course-delivery'])
    ]);         
  }   
}

The format of $combined might seem odd, but I have three different queries creating different object lists that all need to be combined into one JSON array based on 'item_id' as the key. I have the part where all three get combined working, this new array configuration comes from a checkbox situation, thus the need to combine the different values off the same item_id.

1 Answer 1

2

No need for another foreach, you just create the structure along the way. First, initialize the container for the particular item_id.

When an item_id hits again and is not an array, just overwrite it, use the first value (string) and turn it to an array and finally push the value.

$deliveryOptions = [
    (object) ['item_id' => 55, 'value' => 'delivery-online'],
    (object) ['item_id' => 55, 'value' => 'delivery-campus'],
    (object) ['item_id' => 56, 'value' => 'delivery-campus'],
    (object) ['item_id' => 81, 'value' => 'delivery-blended'],
];

$combined = [];
foreach ($deliveryOptions as $row) {
    if (!isset($combined[$row->item_id])) { // initialize if it doesn't exist
        $combined[$row->item_id] = (array) $row; continue;
    }
    if (!is_array($combined[$row->item_id]['value'])) { // if another occurence
        $temp = $combined[$row->item_id]['value']; // get the string initial value
        $combined[$row->item_id]['value'] = []; // turn it into an array
        $combined[$row->item_id]['value'][] = $temp; // and reassign and push inside the array
    }
    $combined[$row->item_id]['value'][] = $row->value; // push the value in the array
}

// $combined = array_values($combined); // array key reindex if needed

Sample output

Sign up to request clarification or add additional context in comments.

2 Comments

This works, thanks! I have not tried casting (array) in front of the value before or using continue.
@hpgodwin yes it's just typecasting on each $row since the input you have is an object on your example, glad this helped. the continue; just skips the current iteration so that it doesn't execute the rest of the code block.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.