1

How can I change the property that belongs to one of returned entry's relationship without affecting the other?

The example query below returns two entries with each having their own set of relationship attached to them

    $tttt = App\ManualTicket::where(function ($checkUser) {
        $checkUser->where("id",'=',408257)
        ->orWhere("id",'=',408258);
    })->with(['same_manual_ticket_group','same_manual_ticket_group.user','same_manual_ticket_group.completed','same_manual_ticket_group.initiator','same_manual_ticket_group.prior_rerouted_ticket','same_manual_ticket_group.ticket_flow_order'])->get();

I expect the code below to change the first entry's relationship id to 'FFFF' and the second entry's relationship id to 'BBBB' however they are both being changed to 'BBBB'.

$tttt[0]['same_manual_ticket_group'][0]['id']='FFFF';
$tttt[1]['same_manual_ticket_group'][0]['id']='BBBB';

Example of data struture enter image description here enter image description here

Yeo Bryan
  • 331
  • 4
  • 24
  • Are you trying to modify collection data? if yes then use collection methods to do so. – Insane Skull Mar 10 '23 at 05:05
  • @InsaneSkull I am just trying to change the value before passing it to the frontend, i do not want to change the value in the database. – Yeo Bryan Mar 10 '23 at 05:29
  • I never said anything about database in first place, Modifying collection does not affect the database, read through collection methods to find out what i am talking about. – Insane Skull Mar 10 '23 at 10:02

3 Answers3

1

You can use the map function of collection or convert $ttt to array and then assign value

$tttt = $tttt->toArray();
$tttt[0]['same_manual_ticket_group'][0]['id']='FFFF';
$tttt[1]['same_manual_ticket_group'][0]['id']='BBBB'; 
Khang Tran
  • 2,015
  • 3
  • 7
  • 10
1

It's better to use Laravel's Collection class built-in function. Here is an example using map function that might suit your case:

$tttt = App\ManualTicket::where(function ($checkUser) {
    $checkUser->where("id", '=', 408257)
        ->orWhere("id", '=', 408258);
    })->with(['same_manual_ticket_group', 'same_manual_ticket_group.user', 'same_manual_ticket_group.completed', 'same_manual_ticket_group.initiator', 'same_manual_ticket_group.prior_rerouted_ticket', 'same_manual_ticket_group.ticket_flow_order'])
      ->get()
      ->map(function ($tt, $index) {
        if ($index == 0) {
          $tt->same_manual_ticket_group->first()->id = 'FFFF';
        } else {
          $tt->same_manual_ticket_group->first()->id = 'BBBB';
        }
        return $tt;
});
francisco
  • 1,387
  • 2
  • 12
  • 23
Nico Tanzil
  • 11
  • 1
  • 3
1

As others have pointed out, you'd have to first turn the collection into an array and then modify the key.

$array = $tttt->toArray();
$array[0]['same_manual_ticket_group'][0]['id']='FFFF';
$array[1]['same_manual_ticket_group'][0]['id']='BBBB';

This happens probably because they are referencing the same model, so they point to the same data.

When you dump the variable, you can see a number next to each class. For example

Collection{#2480

If what you are trying to modify shares numbers, then it's referencing the same object

An easy way to see this is by running the following in php artisan tinker

>>> $mt = new App\ManualTicket
=> App\ManualTicket {#1}
>>> $collection = collect([$mt, $mt]);
=> Illuminate\Support\Collection {#2
    all: [
        App\ManualTicket{#1},
        App\ManualTicket{#1},
    ],
}
>>> $collection->get(0)->something = 'something'; // update only the first one
=> "something"
>>> $collection // show collection again. Surprise, both values updated.
=> Illuminate\Support\Collection {#2
    all: [
        App\ManualTicket{#1
            something: "something",
        },
        App\ManualTicket{#1
            something: "something",
        },
    ],
}

same reference number, both values update. When transforming to an array, you don't have to deal with that. Another possibility (if you know exactly which values to change) is to clone the objects. Here's how that would look in our php artisan tinker example

>>> $clone = clone $collection->get(0);
=> App\ManualTicket{#3
    something: "something",
},
>>> $collection->put(0, $clone);
=> Illuminate\Support\Collection {#2
    all: [
        App\ManualTicket{#3
            something: "something",
        },
        App\ManualTicket{#1
            something: "something",
        },
    ],
}
>>> $collection->get(0)->something = 'something else';
=> "something else"
>>> $collection // show collection again. Surprise, now both values are different.
=> Illuminate\Support\Collection {#2
    all: [
        App\ManualTicket{#3
            something: "something else",
        },
        App\ManualTicket{#1
            something: "something",
        },
    ],
}

Applied to this case:

$cloned = clone $tttt->get(0)->same_manual_ticket_group->get(0);
$cloned->id ='FFFF';
$tttt->get(0)->same_manual_ticket_group->put(0, $cloned);

// no need to clone the second one, it's already a different reference.
$tttt->get(1)->same_manual_ticket_group->get(0)->id ='FFFF';
IGP
  • 14,160
  • 4
  • 26
  • 43