制作Laravel系列的副本

时间:2015-04-20 07:34:27

标签: php laravel

我正在尝试将一个users集合的副本提供给一个雄辩的模型jobs。所以我实际上有:

jobs : [
    1 : {
        users : {
            1: {}
            2: {}
            3: {}
        }
    }
    2 : {
        users : {
            1: {}
            2: {}
            3: {}
        }
    }
]

一旦我得到这个,我将从另一个查询中总结一些数字,基本上为每个工作的每个用户提供一个总数,所以上面的结果可能最终看起来像这样:

jobs : [
    1 : {
        users : {
            1: {
                total: 120
            }
            2: {
                total: 45
            }
            3: {
                total: 12
            }
        }
    }
    2 : {
        users : {
            1: {
                total: 32
            }
            2: {
                total: 4
            }
            3: {
                total: 17
            }
        }
    }
]

除非我似乎无法克隆此用户列表,并且我实际上最终会使所有总计彼此相同:

{  
   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
         }
      }
   }
}

这是我正在做的事情:

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;
}

我的猜测是,我实际上只是创建对同一事物的引用,而实际上只是添加到'master'集合中。如何成功克隆用户以使总计在作业中唯一?

修改

使用数组(如Matheos推荐的那样)会导致一个非常奇怪的错误:

  

ErrorException(E_NOTICE)

     

间接修改重载属性Job :: $ users无效

2 个答案:

答案 0 :(得分:8)

您的问题是您正在克隆$users_list,但这是CollectionUser个对象。在PHP中,当您克隆对象时,任何对象引用的属性仍然是对这些对象的引用,换句话说,这些子对象本身不会被克隆。见__clone

您的代码正在动态添加“总计”。属性User中的每个Collection实例,它实际上会改变该特定User的所有实例的总值,因为它们都是对自身的引用。您需要做的是克隆User的每个子成员(Collection)以及Collection本身。

foreach ($jobs as $job):
    $job->users = clone $users_list;
    $job->users->transform(function($user) { return clone $user; });
endforeach;

可能有更好的方法来做你正在尝试做的事情,但这应该让你去,并希望回答你为什么这样做的问题。

答案 1 :(得分:0)

而不是雄辩的集合尝试使用数组:

$users_list = User::all(['id'])->keyBy('id')->toArray();

您可能还想为“总计”设置初始值

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

        if (! isset($jobs[$chunk->job_id]->users[$chunk->user_id]['total'])) {
            $jobs[$chunk->job_id]->users[$chunk->user_id]['total'] = 0;
        }

        $jobs[$chunk->job_id]->users[$chunk->user_id]['total'] += $chunk->stop_time - $chunk->start_time;

    }
}