Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a multidimensional collection. I want to iterate it and alter some of its child objects and arrays using the map() function: https://laravel.com/docs/5.1/collections#method-map

Sample content:

'address': 'Somestreet 99' 'orders': [ {'id': 11}, {'id': 67}

Example

  $deliveries = $delivery_addresses->map(function($delivery_address){
     $orders = $delivery_address->orders->filter(function($order){
        return $order->id == 67;
     $delivery_address['address'] = 'A different street 44'
     $delivery_address['orders'] = $orders;
     $delivery_address['a_new_attribute'] = 'Some data...';
     return $delivery_address;

Expected result:

'address': 'A different street 44' 'orders': [ {'id': 67} 'a_new_attribute': 'Some data...;

The result is that only string type variables will be changed. Any arrays or objects will stay the same. Why is this and how to get around it? Thanks! =)

Do you have an example collection that would give the result you're describing? Modification of all kinds of data from within map should give desired results as elements of the collection are just overwritten by what you return from your callback. – jedrzej.kurylo Jan 15, 2016 at 9:29 Could you also post the real code that you're executing, not some pseudocode? $old_collection.map won't work in PHP – jedrzej.kurylo Jan 15, 2016 at 9:30 Could you also post a desired result, and what you are actually getting? I am also curious why you are accessing $delivery_address as an object, then assigning a key as an array later. – jardis Jan 15, 2016 at 9:45 @Sturm -- Well, while I didn't know that I also find that a huge can of worms that should never have been opened. :P Shouldn't let people treat objects like arrays, ever. But that's a topic for another day, thanks for the info. – jardis Jan 15, 2016 at 9:58
collect($deliver_addresses)->map(function ($address) use ($input) {
    $address['id']              = $input['id'];
    $address['a_new_attribute'] = $input['a_new_attribute'];
    return $address;
                You are Awesome, I was attemting the same but was missing the use($param) bit so was not able to access data outside the map function.
– Arnaud Bouchot
                Mar 14, 2018 at 15:16
                @MayuriPansuriya upvoted but it is always best to include some explanation with an answer instead of just posting code
– Gharbad The Weak
                Sep 26, 2019 at 20:28
                Note that map does not modify original collection but it returns the modified collection, so you have to assign result to a variable else the code above has no effect.
– KoviNET
                Mar 25, 2022 at 9:35

Addressing your recent edits, try this:

$deliveries = $deliver_addresses->map(function($da) {
    $orders = $da->orders->filter(function($order) {
        return $order->id == 67;
    $da->unused_attribute = $orders->all();
    return $da;

What the case most likely is here is that you are correctly overwriting that attribute. Then when you are attempting to access it Laravel is querying the orders() relationship and undoing your changes. As far as Laravel is concerned these are the same:

$delivery_address->orders;
$delivery_address['orders'];

This is why the changes are only working on objects. If you want to save that permanently then actually save it, if not use a temporary attribute to contain that data.

Since don't want to save any data, just print it as JSON, I'm thinking of converting the collection to an array and then work with whats available - like foreach()... – MikaelL Jan 15, 2016 at 10:22
$paymentMethods = $user->paymentMethods()->map(function($paymentMethod){
            return $paymentMethod->asStripePaymentMethod();

Eloquent collections has a put method (since v5.1), that can be used to add a field to a collection while keeping the 'pipe-style' chaining. It can also be used with the new arrow functions syntax:

    $deliveries = $delivery_addresses
        ->map(fn ($delivery_address) => collect($delivery_address)
            ->put('orders', Orders::where('delivery_addresses_id', '=', $delivery_address->id))
            ->toArray()
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.