I'm trying to give a copy of a collection of users
to an eloquent model jobs
. So I'd effectively have:
jobs : [
1 : {
users : {
1: {}
2: {}
3: {}
}
}
2 : {
users : {
1: {}
2: {}
3: {}
}
}
]
Once I get this, I'm going to sum some numbers from another query to essentially give myself a total for each user on each job, so the above may end up looking like this:
jobs : [
1 : {
users : {
1: {
total: 120
}
2: {
total: 45
}
3: {
total: 12
}
}
}
2 : {
users : {
1: {
total: 32
}
2: {
total: 4
}
3: {
total: 17
}
}
}
]
Except I can't seem to clone this users list, and I'm effectively ending up with all the totals being the same as each other:
{
1:{
id:1,
users:{
1:{
id:1,
total:807
},
2:{
id:2,
total:9
}
}
},
2:{
id:2,
users:{
1:{
id:1,
total:807
},
2:{
id:2,
total:9
}
}
},
3:{
id:3,
users:{
1:{
id:1,
total:807
},
2:{
id:2,
total:9
}
}
}
}
Here is what I am doing:
public function summary()
{
$jobs = Job::all()->keyBy('id');
$users = User::with('closed_time_chunks')->get();
$users_list = User::all(['id'])->keyBy('id');
// I think this is the problem statement:
foreach ($jobs as $job):
$job->users = clone $users_list;
endforeach;
Log::info('Starting');
foreach ($users as $user):
foreach ($user->closed_time_chunks as $chunk):
Log::info('Adding ' . ($chunk->stop_time - $chunk->start_time) . ' to job: ' . $chunk->job_id);
$jobs[$chunk->job_id]->users[$chunk->user_id]['total'] += $chunk->stop_time - $chunk->start_time;
endforeach;
endforeach;
}
My guess is that I am actually just creating a reference to the same thing and any addition is in fact just adding to the 'master' collection. How can I successfully clone the users so that the totals will be unique across jobs?
Using an array (as Matheos recommends) results in a really bizarre error:
ErrorException (E_NOTICE)
Indirect modification of overloaded property Job::$users has no effect
Your problem is that you are cloning your $users_list
, but that is a Collection
of User
objects. In PHP, when you clone an object, any of it's properties that are references to objects remain references to those objects, in other words those child objects do not get cloned themselves. See __clone
Being that your code is dynamically adding a 'total' property to every User
instance in the Collection
, it is effectively altering that total value of all instances of that particular User
, because they are all references to themselves. What you would need to do is clone every child member (User
) of your Collection
, along with the Collection
itself.
foreach ($jobs as $job):
$job->users = clone $users_list;
$job->users->transform(function($user) { return clone $user; });
endforeach;
There are probably better ways to do what you're trying to do, but this should get you going and hopefully answer your question of why too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With