Search code examples
phplaraveleloquentlaravel-collection

How to update a nested value within a nested Laravel collection


I have a deployments Laravel Collection like this:

Illuminate\Support\Collection {#415 ▼
  #items: array:5 [▼
    0 => array:7 [▼
      "id" => 31
      "status" => "active"
      "name" => "Deployment 1"
      "spots" => array:4 [▼
        0 => array:2 [▼
          "id" => 33
          "status" => "active"            <-- Want to change this
        ]
        1 => array:2 [▶]
        2 => array:2 [▶]
        3 => array:2 [▶]
      ]
      "data" => array:3 [▶]
    ]
    1 => array:7 [▶]
    2 => array:7 [▶]
    3 => array:7 [▶]
    4 => array:7 [▶]
  ]
}

I want to update the nested status value to inactive. I have used the Laravel map function, but it only seems to work on collections that have one nesting level. So this...

$this->deployments->map(function ($deployment) {
    $deployment['spots'][0]['status'] = 'inactive';
});
dd($this->deployments);

...leaves $this->deployments untouched.

Also tried using nested map functions obtaining a Call to a member function map() on array exception on second level as second and next nesting levels are considered arrays...

Any thoughts? Thanks in advance.


Solution

  • With the map method, you are almost there. You will have to return the change made in $deployment and do an ->all() at the end to update the collection with the modified values.

    For updating a single spot:

    $deployments = $deployments->map(function($deployment){
        $deployment['spots'][0]['status'] = 'inactive';
        return $deployment;
      })->all();
    

    For updating all spots:

    $deployments = $deployments->map(function($deployment){
        foreach($deployment['spots'] as &$spot){
          $spot['status'] = 'inactive';
        }
        return $deployment;
      })->all();