Laravel 查询获取尚未存在真实数据的日期的虚拟数据
Posted
技术标签:
【中文标题】Laravel 查询获取尚未存在真实数据的日期的虚拟数据【英文标题】:Laravel query get dummy data for days where no real data exists yet 【发布时间】:2021-07-26 03:30:47 【问题描述】:我的 Laravel 项目中有一个查询,它从我的数据库中返回两个日期之间的数据集合,然后按小时分组(但我可以根据自己的喜好更改),我现在想返回数据存在于数据库中之前的“日期”作为构建日期列表的一种方式,可以在我的网页中显示,即使这些天没有数据,我的图表看起来还是一致的。
举个例子:
我想查看过去 30 天的数据作为历史记录,但是这段时间的前 20 天还没有数据,我仍然需要返回这些天的日期键,除了其中没有数据。我目前的代码如下(我用的是Carbon):
$uptimeData = UptimeChecks::where('user_id', 1)
->where('monitor_id', 1)
->where('checked_at', '>=', '2021-01-01 00:00:00')
->where('checked_at', '<=', '2021-01-30 23:59:59')
->orderBy('checked_at', 'asc')
->select('event', 'checked_at')
->get();
$from = Carbon::now()->subDays(60);
$period = CarbonPeriod::create($from, '2021-01-30 23:59:59');
$dates = $period->toArray();
foreach ($dates as $key => $date)
$dates[$key] = Carbon::parse($date)->format('Y-m-d');
$uptimeData = collect($uptimeData);
$uptimeData = $uptimeData->merge($dates);
$uptimeDataTimeline = $uptimeData->groupBy(function ($item, $key)
if (isset($item->checked_at))
$date = Carbon::parse($item->checked_at);
else
$date = Carbon::parse($item);
return $date->format('Y-m-d');
);
即使没有显示“checked_at”列的条目,这是否可以在没有数据的情况下用当天的日期进行欺骗?
更新 03/05 @ 20:30
我已经更新了我的描述以反映解决此问题的最新尝试,我似乎已经构建了我需要的东西,但是有一些问题:
-
我在哪里循环我的
$dates
有没有办法在每个项目中建立一些结构,这样我就不必对我的所有变量和键进行if/else
检查?
由于某种原因,在真实数据之后添加了“假”虚拟日期,例如:1 月 1 日、1 月 2 日、12 月 30 日......我该如何扭转这种情况?
【问题讨论】:
您可以构建一个集合,其中包含您想要的所有日期(如果对视图有用,可能使用默认值),然后将查询结果与其合并。 看起来怎么样? @mikenewbuild 在我的手机上,很难打出来,这里是建立日期范围的方法***.com/a/50854594,这里是你可以在集合上使用的合并方法laravel.com/docs/8.x/collections#method-merge 您应该只获取数据库中实际存在的数据。对于您的场景,您可以在控制器中编写代码,您可以在其中添加空日期以制作所需的格式。 @mikenewbuild 我已经用我相信你所指的内容更新了我的描述,但现在我的数组中没有任何东西?我错过了什么? 【参考方案1】:实现此目的的一种方法是创建所需时间段的日期集合,然后将按日期分组的查询结果合并到其中。
这是一个例子:
$from = '2021-01-01';
$to = '2021-01-31';
$period = CarbonPeriod::create($from, $to);
$dates = collect($period->toArray())->mapWithKeys(function ($date)
return [$date->format('Y-m-d') => []];
);
// $dates = ['2021-01-01' => [], '2021-01-02' => [], ...etc]
$uptimeChecks = UptimeChecks::query()
->where('user_id', 1)
->where('monitor_id', 1)
->whereBetween('checked_at', [$from, $to])
->orderBy('checked_at', 'asc')
->select('event', 'checked_at')
->get();
$uptimeDates = $uptimeChecks->groupBy(function ($item, $key)
return $item->checked_at->format('Y-m-d');
);
// $uptimeDates = ['2021-01-02' => ['event1', 'event2'], ...etc]
$uptimeData = $dates->merge($uptimeDates);
// $uptimeData = ['2021-01-01' => [], '2021-01-02' => ['event1', 'event2'], ...etc]
这假设您将 checked_at
字段转换为 UptimeChecks
模型中的日期。
【讨论】:
NP,很高兴它解决了它! Ps 我注意到你的UptimeChecks
模型是复数,但惯例是它是单数 UptimeCheck
是的,那是因为当您从数据库中获取多条记录时,例如使用 UptimeChecks::where()->get()
似乎是合乎逻辑的,其中单数听起来适合像 UptimeCheck::first()
这样的单个正常运行时间检查,你有什么想法?
一个模型(大致)被设计为代表数据库中的一行,如果你使用first()
,你会得到一个UptimeCheck
的实例,当你运行get()
你会得到一个Collection
(不是模型)可以不包含UptimeCheck
的多个实例或多个实例,所以我总是对模型使用单数。以上是关于Laravel 查询获取尚未存在真实数据的日期的虚拟数据的主要内容,如果未能解决你的问题,请参考以下文章