在ThinkPHP项目开发中,统计模型关联数据的相关数量是常见需求,其中近七天新增关联数量的统计场景非常普遍,比如统计文章近七天新增的评论数、用户近七天新增的订单数等。

模型关联统计基础
ThinkPHP提供了便捷的模型关联统计功能,最常用的两个方法是withCount和whereHas。withCount用于在查询主模型时,同时统计关联模型的数量,返回的结果会新增一个关联方法名_count的字段。whereHas则用于筛选存在满足条件的关联数据的模型。
基础关联统计示例
假设我们有两个模型,User模型和Order模型,一个用户可以有多个订单,关联定义如下:
<?php
namespace appmodel;
use thinkModel;
class User extends Model
{
// 定义用户和订单的一对多关联
public function orders()
{
return $this->hasMany(Order::class);
}
}
如果要统计每个用户的订单总数,可以使用withCount:
<?php
use appmodelUser;
// 统计每个用户的订单总数
$users = User::withCount('orders')->select();
foreach ($users as $user) {
echo "用户ID:{$user->id},订单总数:{$user->orders_count}" . PHP_EOL;
}
统计近七天新增关联数量
要统计近七天新增的关联数量,核心是在关联统计时添加时间筛选条件,筛选关联数据的创建时间在近七天范围内。
实现方式一:结合where条件使用withCount
可以在withCount的闭包函数中添加时间筛选条件,具体实现如下:
<?php
use appmodelUser;
use thinkfacadeDb;
// 获取近七天的开始时间戳
$sevenDaysAgo = strtotime('-7 days');
// 统计每个用户近七天新增的订单数量
$users = User::withCount([
'orders' => function ($query) use ($sevenDaysAgo) {
// 筛选订单创建时间大于等于近七天开始时间
$query->where('create_time', '>=', $sevenDaysAgo);
}
])->select();
foreach ($users as $user) {
echo "用户ID:{$user->id},近七天新增订单数:{$user->orders_count}" . PHP_EOL;
}
实现方式二:使用whereHas筛选后统计
如果只需要统计存在近七天新增订单的用户,同时获取对应的订单数,可以使用whereHas结合withCount:
<?php
use appmodelUser;
use thinkfacadeDb;
$sevenDaysAgo = strtotime('-7 days');
// 筛选存在近七天新增订单的用户,并统计近七天订单数
$users = User::whereHas('orders', function ($query) use ($sevenDaysAgo) {
$query->where('create_time', '>=', $sevenDaysAgo);
})->withCount([
'orders' => function ($query) use ($sevenDaysAgo) {
$query->where('create_time', '>=', $sevenDaysAgo);
}
])->select();
foreach ($users as $user) {
echo "用户ID:{$user->id},近七天新增订单数:{$user->orders_count}" . PHP_EOL;
}
注意事项
- 关联定义中的外键、主键需要正确配置,否则统计结果会不准确。
- 时间字段的类型需要和筛选条件匹配,如果
create_time是datetime类型,可以使用whereTime方法简化时间筛选:$query->whereTime('create_time', '>=', '-7 days')。 - 如果关联数据量较大,建议给关联表的时间字段添加索引,提升统计查询的效率。
常见问题解答
统计结果一直为0怎么办
首先检查关联定义是否正确,然后打印生成的SQL语句,查看时间筛选条件是否生效,确认关联表的create_time字段是否有近七天的数据。
如何统计指定用户近七天新增关联数量
可以先查询指定用户,再使用上述withCount的方式添加时间条件即可,示例如下:
<?php
use appmodelUser;
$userId = 1;
$sevenDaysAgo = strtotime('-7 days');
$user = User::where('id', $userId)->withCount([
'orders' => function ($query) use ($sevenDaysAgo) {
$query->where('create_time', '>=', $sevenDaysAgo);
}
])->find();
if ($user) {
echo "用户ID:{$user->id},近七天新增订单数:{$user->orders_count}" . PHP_EOL;
}