andcl
andcl

Reputation: 3548

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.

Upvotes: 0

Views: 4268

Answers (2)

KingDavid
KingDavid

Reputation: 31

For anyone researching this, a more elegant solution might be:

For updating a single spot:

$data = $deployments->all();
$deployments = data_set($data, 'spots.0.status', 'inactive');

For updating all spots:

$data = $deployments->all();
$deployments = data_set($data, 'spots.*.status', 'inactive');

Upvotes: 3

nice_dev
nice_dev

Reputation: 17805

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();

Upvotes: 2

Related Questions