Skip to content
Advertisement

Transform nested collection in laravel

I have a nested collection that I want to transform, pulling some keys “up a level” and discarding some other keys.

Every item in the collection has an allergens property.

"allergens": [
        {
            "id": 2001,
            "info": "Allergy advice",
            "status": "does_contain",
            "product_id": 71576,
            "allergen_id": 1,
            "allergen": {
                "id": 1,
                "name": "Celery"
            }
        },
        {
            "id": 2002,
            "info": "Allergy advice",
            "status": "may_contain",
            "product_id": 71576,
            "allergen_id": 11,
            "allergen": {
                "id": 11,
                "name": "Peanuts"
            }
        }
    ],

I need to make each items allergens property, look like

"allergens": [
        {
            "id": 1,
            "name": "Celery"
            "status": "does_contain",
        },
        {
            "id": 11,
            "name": "Peanuts"
            "status": "does_contain",
        },
    ],

I’ve tried the following:

$collection = $collection->transform(function ($item, $key) {
    $item->allergens = $item->allergens->map(function ($allergen) {
        return [
            'id' => $allergen->allergen->id,
            'name' => $allergen->allergen->name,
            'status' => $allergen->status,
        ];
    });
    
    return $item;
});

But it doesn’t overwrite the allergens property

Advertisement

Answer

Since you’re posting your collection as JSON, I reverse engineered what your actual collection would look like. Turns out, your transform() works fine as far as I can tell. Maybe that helps you to find differences between my and your collection which might lead you to your problem/solution:

$collection = collect([
  (object)[

    "allergens" => collect([
            (object)[
                "id" => 2001,
                "info" => "Allergy advice",
                "status" => "does_contain",
                "product_id" => 71576,
                "allergen_id" => 1,
                "allergen" => (object)[
                    "id" => 1,
                    "name" => "Celery"
                ]
            ],
            (object)[
                "id" => 2002,
                "info" => "Allergy advice",
                "status" => "may_contain",
                "product_id" => 71576,
                "allergen_id" => 11,
                "allergen" => (object)[
                    "id" => 11,
                    "name" => "Peanuts"
                ]
            ]
    ]),
  ]
]);
$collection = $collection->transform(function ($item, $key) {
    $item->allergens = $item->allergens->map(function ($allergen) {
        return [
            'id' => $allergen->allergen->id,
            'name' => $allergen->allergen->name,
            'status' => $allergen->status,
        ];
    });
    
    return $item;
});
dd($collection);

Result:

IlluminateSupportCollection {#1779 ▼
  #items: array:1 [▼
    0 => {#1791 ▼
      +"allergens": IlluminateSupportCollection {#1775 ▼
        #items: array:2 [▼
          0 => array:3 [▼
            "id" => 1
            "name" => "Celery"
            "status" => "does_contain"
          ]
          1 => array:3 [▼
            "id" => 11
            "name" => "Peanuts"
            "status" => "may_contain"
          ]
        ]
      }
    }
  ]
}
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement