好,所以我要建立一个表来记录一年中每个月的时间条目。我有一个名为$ group_months的变量,如果我转储数据,则会得到以下信息:
Collection {#189 ▼
#items: array:4 [▼
"Comp Time Used" => Collection {#294 ▼
#items: array:3 [▼
10 => "12:00:00"
11 => "09:00:00"
"01" => "12:00:00"
]
}
"Vacation Time Used" => Collection {#324 ▼
#items: array:1 [▼
11 => "04:00:00"
]
}
"Sick Time" => Collection {#327 ▼
#items: array:1 [▼
10 => "03:15:00"
]
}
"OT Accrued" => Collection {#318 ▼
#items: array:1 [▼
10 => "12:00:00"
]
}
]
}
我希望能够提取每个集合的标题并将其用作表的列。因此,我想选择“比较使用时间”以将其用作表中的列。然后,我想提取“ 12:00:00”并将其用于表中的10月行。(10 = 10月)
TableView:
<table class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Overtime Hours</th>
<th scope="col">Compensation Hours</th>
<th scope="col">Vacation</th>
<th scope="col">Personal Hours</th>
<th scope="col">Sick Hours</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Jan</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
</tr>
<tr>
<th scope="row">Feb</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Mar</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Apr</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">May</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Jun</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Jul</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Aug</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Sep</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Oct</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Nov</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">Dec</th>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
时间迁移:
Schema::create('times', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->date('start_day');
$table->text('category');
$table->time('start_time');
$table->time('finish_time');
$table->time('duration');
$table->text('notes');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
TableController:
public function show(User $user)
{
$data = $user->times()->whereYear('start_day', 2019)->get();
$group_months = $data->groupBy(function($entry) {
return $entry->category;
})->map(function($items) {
return $items->groupBy(function($entry) {
return Carbon::parse($entry->start_day)->format('m');
})
->map(function($items) {
$duration = $items->first()->duration;
return $duration;
});
});
return view('table.show', compact('data','group_months'));
答案 0 :(得分:1)
您当前正在查询所有数据,将其分组在内存中并不是很有效。相反,您应该尽可能多地推送到数据库。这也意味着仅查询相关数据:category
,month
和sum(duration)
public function show(User $user)
{
$data = $user->times()
->whereYear('start_day', 2019)
->groupBy('category', \DB::raw('month(start_date)'))
->select([
'category',
\DB::raw('month(start_date) as month'),
\DB::raw('sum(duration) as duration'),
])
->orderBy(\DB::raw('month(start_date)'))
->get()
->mapToGroups(function ($item) {
$month = \DateTime::createFromFormat('!m', $item['month'])->format('M');
return [$month => [$item['category'] => $this->formatDuration($item['duration'])]];
})
->mapWithKeys(function ($item, $key) {
return [$key => $item->collapse()];
});
return view('table.show', compact('data'));
}
private function formatDuration($seconds)
{
$duration = '';
if ($seconds < 0) {
$duration = '-';
$seconds = abs($seconds);
}
$hours = floor($seconds / 3600);
$seconds -= $hours * 3600;
$minutes = floor($seconds / 60);
$seconds -= $minutes * 60;
return $duration . sprintf('%d:%02d:%02d', $hours, $minutes, $seconds);
}
此时,$data
包含以下结构:
[
'Jan' => [
'Category 1' => '1:20:40',
'Category 2' => '15:05:40',
'Category 4' => '0:00:50'
],
'Feb' => [
'Category 2' => '2:30:15',
'Category 3' => '4:45:30'
]
]
我们可以使用此数据以通用的方式使用表索引作为月份号来生成表。
<table class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">Month</th>
<th scope="col">Overtime Hours</th>
<th scope="col">Compensation Hours</th>
<th scope="col">Vacation</th>
<th scope="col">Personal Hours</th>
<th scope="col">Sick Hours</th>
</tr>
</thead>
<tbody>
@foreach($data as $month => $row)
<tr>
<th scope="row">{{ $month }}</th>
<td>{{ $row['Overtime Hours'] ?? '-' }}</td>
<td>{{ $row['Compensation Hours'] ?? '-' }}</td>
<td>{{ $row['Vacation'] ?? '-' }}</td>
<td>{{ $row['Personal Hours'] ?? '-' }}</td>
<td>{{ $row['Sick Hours'] ?? '-' }}</td>
</tr>
@endforeach
</tbody>
</table>
如果您希望在表格中显示每个月,即使该月没有可用数据,也可以使用array_fill(1, 12, [])
作为基数将缺失的索引添加到集合中:
public function show(User $user)
{
$data = collect(array_fill(1, 12, []))
->replace(
$user->times()
->whereYear('start_day', 2019)
->groupBy('category', \DB::raw('month(start_date)'))
->select([
'category',
\DB::raw('month(start_date) as month'),
\DB::raw('sum(duration) as duration'),
])
->orderBy(\DB::raw('month(start_date)'))
->get()
->mapToGroups(function ($item) {
return [$item['month'] => [
$item['category'] => $this->formatDuration($item['duration'])
]];
})
->mapWithKeys(function ($item, $key) {
return [$key => $item->collapse()];
})
)
->mapToGroups(function ($item, $key) {
$month = \DateTime::createFromFormat('!m', $key)->format('M');
return [$month => $item];
});
return view('table.show', compact('data'));
}