我需要根据$request
的日期发送每个日期的观看次数。根据我在控制器中的查询,我得到的图表数据如下:
[{"time":"2016-05-01","count":2},{"time":"2016-05-02","count":3},{"time":"2016-05-03","count":7},{"time":"2016-05-07","count":3}]
对于该数据,我需要添加0
的缺失日期和观看次数。我正在尝试关注this example,但我似乎无法为我的示例实现此解决方案。这是我的方法:
public function timelines(Request $request){
$from = $request['from'];
$to = $request['to'];
$data = DB::table($request['option'])
->select(DB::raw('DATE(created_at) as time'), DB::raw('count(*) as count'))
->whereDate('created_at', '>=', date($from).' 00:00:00')
->whereDate('created_at', '<=', date($to).' 00:00:00')
->groupBy('time')
->get();
return json_encode($data);
}
更新的代码:
public function timelines(Request $request){
$from = $request['from'];
$to = $request['to'];
$date = $from;
$data = [];
if ($request['option'] == 'time'){
$data = View::groupBy('time')
->orderBy('time', 'ASC')
->whereDate('created_at', '>=', date($from).' 00:00:00')
->whereDate('created_at', '<=', date($to).' 00:00:00')
->get([
DB::raw('Hour(created_at) as time'),
DB::raw('COUNT(*) as "count"')
]);
}
else {
while($date <= $to) {
$formattedDate = date('Y-m-d', strtotime($date));
$results = DB::table($request['option'])
->select(DB::raw('DATE(created_at) as time'), DB::raw('count(*) as count'))
->whereDate('created_at', '=', $formattedDate .' 00:00:00')
->groupBy('time')
->get();
if(count($results)) {
$data[] = [
'time' => $formattedDate,
'count' => $results[0]->count
];
} else {
$data[] = [
'time' => $formattedDate,
'count' => 0
];
}
$date = strtotime('+1 day', strtotime($formattedDate));
}
}
return json_encode($data);
}
有了这个,我只计算我发送的第一个日期,例如:
[{"time":"2016-03-16","count":0}]
答案 0 :(得分:1)
这个解决方案对我有用,我首先创建了一个包含时间范围内所有日期的数组,日期设置为键,计数值设置为0,然后在DB中查询后替换值,同样包含查询中计数值的数组:
$period = new DatePeriod( new DateTime($from), new DateInterval('P1D'), new DateTime($to));
$dbData = [];
foreach($period as $date){
$range[$date->format("Y-m-d")] = 0;
}
$data = DB::table($request['option'])
->select(DB::raw('DATE(created_at) as time'), DB::raw('count(*) as count'))
->whereDate('created_at', '>=', date($from).' 00:00:00')
->whereDate('created_at', '<=', date($to).' 00:00:00')
->groupBy('time')
->get();
foreach($data as $val){
$dbData[$val->time] = $val->count;
}
$data = array_replace($range, $dbData);
}
return json_encode($data);
答案 1 :(得分:0)
array_replace
而不是您可以在循环中执行此操作。像这样。
$period = new DatePeriod( new DateTime($from), new DateInterval('P1D'), new DateTime($to));
$dbData = [];
foreach($period as $date){
$range[$date->format("Y-m-d")] = 0;
}
$data = DB::table($request['option'])
->select(DB::raw('DATE(created_at) as time'), DB::raw('count(*) as count'))
->whereDate('created_at', '>=', date($from).' 00:00:00')
->whereDate('created_at', '<=', date($to).' 00:00:00')
->groupBy('time')
->get();
foreach($data as $val){
$range[$val->time] = $val->count; //Filling value in the array
}
//$data = array_replace($range, $dbData); <-- No need to do this.
return json_encode($range);
答案 2 :(得分:0)
Maro和Rutvij Kothari提供的答案是正确的,这是相同逻辑的更优雅/更简化的版本。
我不是使用2个单独的for循环,而是使用array_map函数执行相同的操作。
$data = DB::table($request['option'])
->select(DB::raw('DATE(created_at) as time'), DB::raw('count(*) as count'))
->whereDate('created_at', '>=', date($from).' 00:00:00')
->whereDate('created_at', '<=', date($to).' 00:00:00')
->groupBy('time')
->get()
->keyBy('time');
$range = array_map(function ($e) use ($data) {
$date = Carbon::parse($e)->format('Y-m-d');
return empty($data[$date]) ? 0 : $data[$date]->count;
}, CarbonPeriod::create(Carbon::parse($from), Carbon::parse($to))->toArray());
return json_encode($range);
此外,如果要生成最近7天之类的范围,请使用Carbon中的内置函数
CarbonPeriod::create(Carbon::now()->subDays(7), Carbon::now());
答案 3 :(得分:-1)
您可以遍历要显示的所有日期,并在while循环中计算它们:
public function timelines(Request $request){
$from = $request['from'];
$to = $request['to'];
$date = $from;
$data = array();
while($date <= $to) {
$formattedDate = date('Y-m-d', $date);
$results = DB::table($request['option'])
->select(DB::raw('count(*) as count'))
->whereDate('created_at', '=', $formattedDate .' 00:00:00')
->groupBy('time')
->get();
if(count($results)) {
$data[] = [
'time' => $formattedDate,
'count' => $results[0]->count
];
} else {
$data[] = [
'time' => $formattedDate,
'count' => 0
];
}
$date = strtotime('+1 day', $date);
}
return json_encode($data);
}