You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent按时间范围统计文件下载次数方案问询

统计下载记录的时段下载次数

我有一张用于记录下载信息的Download表,数据库中的每条记录代表一次下载,表结构如下:

id
file_id
created_at
updated_at

我已在File与Download模型间建立关联,可通过以下方式获取文件对应的下载记录:

$file->downloads

// 返回结果:
Illuminate\Database\Eloquent\Collection {#4585
    all: [
      App\Models\Download {#4587
        id: 12,
        file_id: 2,
        created_at: "2022-09-02 12:05:12",
        updated_at: "2022-09-02 12:05:12",
      },
      App\Models\Download {#4597
        id: 13,
        file_id: 1,
        created_at: "2022-09-03 12:05:14",
        updated_at: "2022-09-03 12:05:14",
      },
      App\Models\Download {#4598
        id: 14,
        file_id: 1,
        created_at: "2022-09-03 12:08:33",
        updated_at: "2022-09-03 12:08:33",
      },
    ],
  }

我现在需要选择一个时间范围(日、周或月),统计该范围内各时段的下载次数。以按日统计为例,期望得到如下格式的结果:

[
  '2022-09-02' => 1,
  '2022-09-03' => 2,
]

我能想到几种实现方法但都不够理想,问题不在于日期比较,而在于如何统计次数,希望得到简洁的解决方案。


更新:

根据提示我使用了groupBy方法,代码如下:

$grouped = $file->downloads->groupBy(function ($item, $key) {
    return $item->created_at->format('Y M d');
});

// 返回结果:
Illuminate\Database\Eloquent\Collection {#4648
     all: [
       "2022 Sep 02" => Illuminate\Database\Eloquent\Collection {#4651
         all: [
           App\Models\Download {#4625
             id: 12,
             file_id: 2,
             created_at: "2022-09-02 12:05:12",
             updated_at: "2022-09-02 12:05:12",
           },
         ],
       },
       "2022 Sep 03" => Illuminate\Database\Eloquent\Collection {#4649
         all: [
           App\Models\Download {#4598
             id: 13,
             file_id: 1,
             created_at: "2022-09-03 12:05:14",
             updated_at: "2022-09-03 12:05:14",
           },
           App\Models\Download {#4630
             id: 14,
             file_id: 1,
             created_at: "2022-09-03 12:08:33",
             updated_at: "2022-09-03 12:08:33",
           },
         ],
       },
     ],
   }    

这已经接近目标,但还不是我想要的格式:

[
  '2022-09-02' => 1,
  '2022-09-03' => 2,
]

解决方案

你只需要调整日期格式,并将分组后的集合转为对应数量即可:

$downloadStats = $file->downloads->groupBy(function ($item) {
    // 调整日期格式为你需要的Y-m-d
    return $item->created_at->format('Y-m-d');
})->map(function ($group) {
    // 将每个分组的集合转为数量
    return $group->count();
})->toArray();

执行后就能得到你期望的键为日期字符串、值为对应下载次数的数组。

如果需要支持按周或月统计,只需修改format的参数:

  • 按周统计:可使用'Y-W'(年份+周数),或取每周第一天格式化为Y-m-d:$item->created_at->startOfWeek()->format('Y-m-d')
  • 按月统计:使用'Y-m'(年份+月份)

更高效的数据库层面统计方案

如果数据量较大,建议直接在数据库完成分组统计,避免加载所有模型实例:

// 按日统计(MySQL)
$downloadStats = $file->downloads()
    ->selectRaw('DATE(created_at) as date, COUNT(*) as count')
    ->groupBy('date')
    ->pluck('count', 'date')
    ->toArray();

// 按周统计(MySQL)
$downloadStats = $file->downloads()
    ->selectRaw('YEARWEEK(created_at) as week, COUNT(*) as count')
    ->groupBy('week')
    ->pluck('count', 'week')
    ->toArray();

// 按月统计(MySQL)
$downloadStats = $file->downloads()
    ->selectRaw('DATE_FORMAT(created_at, "%Y-%m") as month, COUNT(*) as count')
    ->groupBy('month')
    ->pluck('count', 'month')
    ->toArray();

这种方式性能更优,返回结果同样是符合需求的键值对数组。

内容的提问来源于stack exchange,提问作者Brainmaniac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:03:33