Laravel collection multi level groupBy 插入新项目而不检查每个级别的键
Laravel collection multi level groupBy insert new items without checking each level's key
Laravel 集合现在内置了一个很棒的多级 groupBy 函数,但我正在努力寻找一种插入新项目的合理方法。
例如:
$this->myCollection = EloquentModel::all()->groupBy(['key1','key2','key3','key4']);
非常好,易于设置和访问。对于这个例子,我假设每个键都是一个数字
$this->myCollection[1][2][3][4] = new EloquentModel([insert => stuffHere]);
如果嵌套位置 [1]、[2] 和 [3] 中已经有项目,那么我可以添加新项目或覆盖 [4] 处的现有项目,但如果任何嵌套位置1 到 3 丢失我得到一个错误
Undefined offset: 1 (or 2 or 3 depending upon which is missing)
目前我正在使用以下函数调用插入结构函数:
if (!$this->myCollection->has()) {
$this->myCollection[] = new Collection;
}
if (!$this->myCollection[]->has()) {
$this->myCollection[][] = new Collection;
}
if (!$this->myCollection[][]->has()) {
$this->myCollection[][][] = new Collection;
}
$this->myCollection[][][][] = $itemFor4;
我发现 groupBy 嵌套非常有用,除了不能干净地处理我的插入。
一些示例数据 - 请假设有 > 100k 条这样的记录:
['username'=> 'a user name', 'course', => 'a coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 23 // One of 52 weeks, [lots more data]]
['username'=> 'another user name', 'course', => 'another coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 23 // One of 52 weeks, [lots more data]]
['username'=> 'a user name', 'course', => 'another coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 24 // One of 52 weeks, [lots more data]]
['username'=> 'another user name', 'course', => 'a coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 24 // One of 52 weeks, [lots more data]]
代替现实生活中的用户名和课程,它将是代表该特定用户和该课程的代码。
数据将包括 activity 的分钟数、activity 的计数、activity 的等级、activity 的早晚等。
我认为您可以 extend the collection,添加自定义 insertDeep
函数。
一个想法:
Collection::macro('insertDeep', function (array $path, $value) {
$key = array_shift($path);
if (count($path) === 0) {
$this->put($key, $value);
return $this;
}
if (!$this->has($key)) {
$this->put($key, new Collection());
}
return $this->get($key)->insertDeep($path, $value);
});
然后你可以简单地在你的集合上调用这个方法:
$this->myCollection->insertDeep([, , , ], $itemFor4);
我刚刚试了一下,它应该可以正常工作:
$coll = new Collection();
$coll->insertDeep(['a', 'b', 'c', 'd'], 'test');
$coll->toArray();
// Result
[
"a" => [
"b" => [
"c" => [
"d" => "test",
],
],
],
]
免责声明:如果您指定一个键已存在但其值不是集合的路径,此函数将失败
Laravel 集合现在内置了一个很棒的多级 groupBy 函数,但我正在努力寻找一种插入新项目的合理方法。
例如:
$this->myCollection = EloquentModel::all()->groupBy(['key1','key2','key3','key4']);
非常好,易于设置和访问。对于这个例子,我假设每个键都是一个数字
$this->myCollection[1][2][3][4] = new EloquentModel([insert => stuffHere]);
如果嵌套位置 [1]、[2] 和 [3] 中已经有项目,那么我可以添加新项目或覆盖 [4] 处的现有项目,但如果任何嵌套位置1 到 3 丢失我得到一个错误
Undefined offset: 1 (or 2 or 3 depending upon which is missing)
目前我正在使用以下函数调用插入结构函数:
if (!$this->myCollection->has()) {
$this->myCollection[] = new Collection;
}
if (!$this->myCollection[]->has()) {
$this->myCollection[][] = new Collection;
}
if (!$this->myCollection[][]->has()) {
$this->myCollection[][][] = new Collection;
}
$this->myCollection[][][][] = $itemFor4;
我发现 groupBy 嵌套非常有用,除了不能干净地处理我的插入。
一些示例数据 - 请假设有 > 100k 条这样的记录:
['username'=> 'a user name', 'course', => 'a coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 23 // One of 52 weeks, [lots more data]]
['username'=> 'another user name', 'course', => 'another coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 23 // One of 52 weeks, [lots more data]]
['username'=> 'a user name', 'course', => 'another coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 24 // One of 52 weeks, [lots more data]]
['username'=> 'another user name', 'course', => 'a coursename', 'activity_type' => 'one of 100s of activity names', 'reporting_week' => 24 // One of 52 weeks, [lots more data]]
代替现实生活中的用户名和课程,它将是代表该特定用户和该课程的代码。
数据将包括 activity 的分钟数、activity 的计数、activity 的等级、activity 的早晚等。
我认为您可以 extend the collection,添加自定义 insertDeep
函数。
一个想法:
Collection::macro('insertDeep', function (array $path, $value) {
$key = array_shift($path);
if (count($path) === 0) {
$this->put($key, $value);
return $this;
}
if (!$this->has($key)) {
$this->put($key, new Collection());
}
return $this->get($key)->insertDeep($path, $value);
});
然后你可以简单地在你的集合上调用这个方法:
$this->myCollection->insertDeep([, , , ], $itemFor4);
我刚刚试了一下,它应该可以正常工作:
$coll = new Collection();
$coll->insertDeep(['a', 'b', 'c', 'd'], 'test');
$coll->toArray();
// Result
[
"a" => [
"b" => [
"c" => [
"d" => "test",
],
],
],
]
免责声明:如果您指定一个键已存在但其值不是集合的路径,此函数将失败