如何基于时间过滤Laravel后台三个预订数据统计方法?
解决方案:为预订统计方法添加时间过滤逻辑
首先得先修正你代码里的小问题——每个Reservations::where('user_id', request('user_id')后面都少了闭合的括号,这个先补上,不然会直接报错。
接下来咱们分两步实现时间过滤:提取公共逻辑避免重复代码 + 给每个查询添加时间范围条件。
第一步:封装日期参数处理和过滤的公共方法
为了不让三个方法里重复写相同的日期解析和过滤逻辑,咱们在类里添加两个私有方法:一个用来获取并解析前端传的时间参数,另一个用来给查询构造器添加时间过滤条件。
use Carbon\Carbon; // ... /** * 解析前端传递的时间过滤参数 * @return array 包含fromDate和toDate的数组(Carbon实例或null) */ private function getDateFilterParams() { // 从请求中获取filterByPeriod,默认是空数组防止报错 $filterPeriod = request()->get('filterByPeriod', []); // 解析日期并设置为当天的开始/结束时间,确保范围是完整的一天 $fromDate = isset($filterPeriod['from']) ? Carbon::parse($filterPeriod['from'])->startOfDay() : null; $toDate = isset($filterPeriod['to']) ? Carbon::parse($filterPeriod['to'])->endOfDay() : null; return compact('fromDate', 'toDate'); } /** * 给查询构造器添加时间过滤条件 * @param \Illuminate\Database\Eloquent\Builder $query 查询构造器实例 * @param Carbon|null $fromDate 开始日期 * @param Carbon|null $toDate 结束日期 * @return \Illuminate\Database\Eloquent\Builder */ private function applyDateFilterToQuery($query, $fromDate, $toDate) { // 这里替换成你实际的日期字段!比如如果是form_submissions表的created_at,就改成form_submissions.created_at $dateField = 'reservations.created_at'; if ($fromDate) { $query->where($dateField, '>=', $fromDate); } if ($toDate) { $query->where($dateField, '<=', $toDate); } return $query; }
第二步:修改三个统计方法
现在只需要在每个方法里调用上面的公共方法,就能轻松添加时间过滤了:
1. getReservationSources 方法
private function getReservationSources() { // 获取解析后的日期参数 ['fromDate' => $fromDate, 'toDate' => $toDate] = $this->getDateFilterParams(); return Reservations::where('user_id', request('user_id')) // 应用时间过滤 ->tap(function ($query) use ($fromDate, $toDate) { $this->applyDateFilterToQuery($query, $fromDate, $toDate); }) ->leftJoin('tracking_codes', 'form_submissions.tracking_code_id', '=', 'tracking_codes.id') ->leftJoin('tracking_sources', 'tracking_sources.id', '=', 'tracking_codes.tracking_source_id') ->select(DB::raw("count(form_submissions.id) as value, tracking_sources.name as name")) ->groupBy('tracking_sources.name') ->orderBy('value', 'desc') ->get(); }
2. getReservationTrackingCodes 方法
private function getReservationTrackingCodes() { ['fromDate' => $fromDate, 'toDate' => $toDate] = $this->getDateFilterParams(); return Reservations::where('user_id', request('user_id')) ->tap(function ($query) use ($fromDate, $toDate) { $this->applyDateFilterToQuery($query, $fromDate, $toDate); }) ->leftJoin('tracking_codes', 'form_submissions.tracking_code_id', '=', 'tracking_codes.id') ->select(DB::raw('count(tracking_codes.id) as value, tracking_codes.label as name')) ->groupBy('tracking_codes.label') ->orderBy('value', 'desc') ->take(10) ->get(); }
3. getReservationReferrers 方法
private function getReservationReferrers() { ['fromDate' => $fromDate, 'toDate' => $toDate] = $this->getDateFilterParams(); return Reservations::where('user_id', request('user_id')) ->tap(function ($query) use ($fromDate, $toDate) { $this->applyDateFilterToQuery($query, $fromDate, $toDate); }) ->select(DB::raw("count(form_submissions.id) as value, form_submissions.referrer as name")) ->groupBy('form_submissions.referrer') ->orderBy('value', 'desc') ->take(10) ->get(); }
关键注意事项
- 日期字段替换:一定要把
$dateField改成你实际表中的日期字段(比如form_submissions.created_at或者reservations.reservation_date),不然过滤不会生效。 - 参数容错:用
isset和默认空数组处理,避免前端没传filterByPeriod时出现报错。 - 时间范围准确性:
startOfDay()和endOfDay()确保过滤的是完整的日期区间,比如用户选from:2024-05-01,会从当天00:00:00开始统计,to:2024-05-31会到当天23:59:59结束。
内容的提问来源于stack exchange,提问作者PrStandup
相关产品推荐
相关产品推荐

