trunks
trunks

Reputation: 147

Merging two complex objects in PHP without repeating

I have two data objects in JSON format and I'd like to merge them based on ID.

JSON 1:

{
    "teams": {
        "home": {
            "formation": "25",
            "players": [{
                "id": "13112",
                "name": {
                    "surname": "Kaiser"
                },
                "shirt": "1"
            }]
        },
        "away": {
            "formation": "21",
            "players": [{
                "id": "73560",
                "name": {
                    "surname": "Luthe"
                },
                "shirt": "1"
            }]
        }
    }
}

JSON 2:

{
    "items": {
        "13112": [{
            "type": 31,
            "time": "52:31"
        }],
        "73560": [{
            "type": 30,
            "time": "84:27"
        }]
    }
}

I have two objects [teams][home] and [teams][away] and I want to add the keys and values of [type] and [time] from JSON 2 based on the id of each player.

What I've done so far:

$decode_one = json_decode($str,TRUE);
$decode_two = json_decode($str2,TRUE);


foreach($decode_one['teams']['home']['players'] as $key => $value){
    foreach($decode_two['items'] as $key2 => $value2){
        if($value['id'] == $key2){
            $decode_one['teams']['home']['players'][$key]['type'] = $value2['0']['type'];
            $decode_one['teams']['home']['players'][$key]['time'] = $value2['0']['time'];
        } 
    }
}

The output is what I've expected:

{
  "teams": {
    "home": {
      "formation": "25",
      "players": [
        {
          "id": "13112",
          "name": {
            "surname": "Kaiser"
          },
          "shirt": "1",
          "type": 31,
          "time": "52:31"
        }
      ]
    },
    "away": {
      "formation": "21",
      "players": [
        {
          "id": "73560",
          "name": {
            "surname": "Luthe"
          },
          "shirt": "1"
        }
      ]
    }
  }
}

But I want to add the keys and values of [type] and [time] from JSON 2 for [away][players] as well. What's the best way to approach this? Should I repeat again the same foreach loop?

Thank you

Upvotes: 0

Views: 62

Answers (2)

RiggsFolly
RiggsFolly

Reputation: 94662

This will do what you require and parse the array only once

$str = '{"teams": {"home": {"formation": "25","players": [{"id": "13112","name": {"surname": "Kaiser"},"shirt": "1"}]},"away": {"formation": "21","players": [{"id": "73560","name": {"surname": "Luthe"},"shirt": "1"}]}}}';

$str2 = '{"items": {"13112": [{"type": 31,"time": "52:31"}],"73560": [{"type": 30,"time": "84:27"}]}}';



// leave data as an Object
$decode_one = json_decode($str);
$decode_two = json_decode($str2);


foreach($decode_one->teams as $homeOrAway => $haObj){

    foreach($haObj->players as $eachPlayer => $player){    

        foreach($decode_two->items as $playerId => $playerInfo){
            if($player->id == $playerId){
                $decode_one->teams->{$homeOrAway}->players[$eachPlayer]->type = $playerInfo[0]->type;
                $decode_one->teams->{$homeOrAway}->players[$eachPlayer]->time = $playerInfo[0]->time;
            } 
        }
    }
}
print_r($decode_one);

RESULT

stdClass Object
(
    [teams] => stdClass Object
        (
            [home] => stdClass Object
                (
                    [formation] => 25
                    [players] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 13112
                                    [name] => stdClass Object
                                        (
                                            [surname] => Kaiser
                                        )

                                    [shirt] => 1
                                    [type] => 31
                                    [time] => 52:31
                                )

                        )

                )

            [away] => stdClass Object
                (
                    [formation] => 21
                    [players] => Array
                        (
                            [0] => stdClass Object
                                (
                                    [id] => 73560
                                    [name] => stdClass Object
                                        (
                                            [surname] => Luthe
                                        )

                                    [shirt] => 1
                                    [type] => 30
                                    [time] => 84:27
                                )

                        )

                )

        )

Upvotes: 1

user125661
user125661

Reputation: 1568

To prevent repeating yourself, you could define a function that takes two arrays and merges them the way you want. Like so:

function combinePlayersData(&$playersData, $extraData) {
    foreach ($playersData as $key => $value) {
        if (array_key_exists($key, $extraData) {
            $playersData[$key] = array_merge($value, $extraData[$key]);
        }
    }
}

Then just call this function twice:

$decode_one = json_decode($str, true);
$decode_two = json_decode($str2, true);


combinePlayersData($decode_one['teams']['home']['players'], $decode_two['items']);
combinePlayersData($decode_one['teams']['away']['players'], $decode_two['items']);

Upvotes: 1

Related Questions