Laravel Eloquent whereIn,从数据库中检索记录,包括缺少日期

时间:2016-12-17 23:03:03

标签: php database laravel eloquent laravel-5.3

我是Laravel的新手。

我正在制作应用程序来计算您的日常步数。
我正在构建API,所以当数组中选定的天数没有DB的结果时,我需要返回0步。

但是,如果有些日子的数据可以返回实际步骤,并且在其他日子返回0。 我试过这个:

$steps = Step::whereIn('date', $dates)
             ->where('user_id', Auth::id())
             ->get();

但它只返回匹配。正如我写的那样,我想要返回所有日子的数据,而不仅仅是数据库中的数天。请帮忙:)

3 个答案:

答案 0 :(得分:2)

这对于简单的查询永远不可能,因为数据库无法提供任何内容,它不知道。 您可以通过逐步迭代结果并使用0值添加所有缺少日期或通过向包含所有日期的数据库添加表来解决此问题,然后在查询中将其与步骤表连接起来。

答案 1 :(得分:2)

实际上,您必须有一个表格列出您列出的所有日期。因为如果表中存在记录,您只能获取日期。另一种选择是在PHP中为所有日期创建一个循环,但这会产生大量不是最佳解决方案的查询。

如果您有日期表,可以将其与步骤表一起使用,并可以使用COALESCE命令。我建议您将查询编写为纯SQL,然后将其转换为Eloquent查询。

答案 2 :(得分:1)

如果您不想将空记录添加到数据库中以查找缺少的日期 这会是头痛

$dates = [
  '2016-12-01',
  '2016-12-02',
  ...
  '2016-12-31'
];
$records = Step::whereIn('date', $dates)
               ->where('user_id', Auth::id())
               ->get();

$steps = [];
$dates = array_flip($dates);      // flipping array like: ['2016-12-01' => 0, '2016-12-02' => 1, ...]
foreach($records AS $record) {    // iterating records
  $steps[] = $record;             // collecting records
  unset($dates[$record->date]);   // removing date that has record for that day
}

$dates = array_flip($dates);      // flipping back: [0 => '2016-12-01', ...]
foreach($dates as $date) {        // iterating dates that do not have data in db and creating model objects from them
  // creating missing record "on the fly"
  $Step = new Step([
    'date' => $date, 
    'user_id' => Auth::id(), 
    'steps' => 0
  ]);
  $Step->save();
  $steps[] = $Step; // adding model instance to resulting array
}

usort($steps, function($a, $b) { // sorting array of steps by date
  if(strtotime($a->date) > strtotime($b->date)) return 1;
  if(strtotime($a->date) < strtotime($b->date)) return -1;
  return 0;
});




所以我的建议是让一些控制台命令(/app/Console/Commands/)每晚进行处理,并确保所有记录都是一致的。

我的意思是创建一些后台批处理过程,如果用户没有该日期的记录,它将“关闭当天”并在数据库中创建一些记录。

这个建议简化了所有内容,因此您的控制器将像往常一样获取数据而无需任何额外的计算,迭代等。