skip to Main Content

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 = AppManualTicket::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

3

Answers


  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'; 
    
    Login or Signup to reply.
  2. 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 = AppManualTicket::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;
    });
    
    Login or Signup to reply.
  3. 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 AppManualTicket
    => AppManualTicket {#1}
    >>> $collection = collect([$mt, $mt]);
    => IlluminateSupportCollection {#2
        all: [
            AppManualTicket{#1},
            AppManualTicket{#1},
        ],
    }
    >>> $collection->get(0)->something = 'something'; // update only the first one
    => "something"
    >>> $collection // show collection again. Surprise, both values updated.
    => IlluminateSupportCollection {#2
        all: [
            AppManualTicket{#1
                something: "something",
            },
            AppManualTicket{#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);
    => AppManualTicket{#3
        something: "something",
    },
    >>> $collection->put(0, $clone);
    => IlluminateSupportCollection {#2
        all: [
            AppManualTicket{#3
                something: "something",
            },
            AppManualTicket{#1
                something: "something",
            },
        ],
    }
    >>> $collection->get(0)->something = 'something else';
    => "something else"
    >>> $collection // show collection again. Surprise, now both values are different.
    => IlluminateSupportCollection {#2
        all: [
            AppManualTicket{#3
                something: "something else",
            },
            AppManualTicket{#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';
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search