Laravel - 填写数据库

时间:2016-05-23 11:03:55

标签: php mysql eloquent laravel-5.2

我需要根据$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}]

4 个答案:

答案 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)

@Marco完美地回答了这个问题,但我想做一点改进。无需调用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);
}