如何在Laravel中计算数组内赞助ID的剩余名额?
Laravel中计算赞助名额剩余量的实现方案
需求说明
需要检查指定赞助ID数组中,每个赞助的实际使用次数是否超出sponsorship_items表对应记录的spots(名额)字段值,并最终计算每个赞助的剩余名额:
- 数据库结构:
sponsorship_items表:包含id、title、spots字段,示例数据中sponsor1名额为2,sponsor2名额为5user_sponsorships表:记录用户与赞助ID的关联关系,示例中sponsor1被关联2次,sponsor2被关联1次
- 输入:赞助ID数组
[1,2] - 预期输出:
$response = [ "sponsor1" => 0, // 2个名额已用完 "sponsor2" => 4, // 5个名额仅使用1次 ];
实现代码方案
假设你已经有基础的Laravel模型(SponsorshipItem对应sponsorship_items表,UserSponsorship对应user_sponsorships表),可以按照以下步骤完善代码:
1. 获取指定赞助的基础名额数据
先批量查询输入数组中对应的赞助项,只拉取需要的字段以提升性能:
$sponsorshipIds = [1, 2]; // 以ID为键组织赞助项数据,方便后续快速匹配 $sponsorshipItems = \App\Models\SponsorshipItem::whereIn('id', $sponsorshipIds) ->select('id', 'title', 'spots') ->get() ->keyBy('id');
2. 统计各赞助的实际使用次数
如果还未获取使用次数,可以直接通过数据库统计:
$usageCounts = \App\Models\UserSponsorship::whereIn('sponsorship_id', $sponsorshipIds) ->select('sponsorship_id', \DB::raw('count(*) as usage_count')) ->groupBy('sponsorship_id') ->pluck('usage_count', 'sponsorship_id') ->toArray();
如果已经有统计好的$usageCounts(比如键为赞助ID、值为使用次数的数组),可以直接复用。
3. 计算剩余名额并构建响应
遍历赞助项,结合使用次数计算剩余名额,同时确保剩余名额不会出现负数:
$response = []; foreach ($sponsorshipItems as $item) { // 没有使用记录时默认使用次数为0 $usedCount = $usageCounts[$item->id] ?? 0; // 剩余名额 = 总名额 - 使用次数,最低为0(避免超用时出现负数) $remainingSpots = max($item->spots - $usedCount, 0); $response[$item->title] = $remainingSpots; }
完整代码示例
$sponsorshipIds = [1, 2]; // 获取赞助项基础数据 $sponsorshipItems = \App\Models\SponsorshipItem::whereIn('id', $sponsorshipIds) ->select('id', 'title', 'spots') ->get() ->keyBy('id'); // 统计使用次数 $usageCounts = \App\Models\UserSponsorship::whereIn('sponsorship_id', $sponsorshipIds) ->select('sponsorship_id', \DB::raw('count(*) as usage_count')) ->groupBy('sponsorship_id') ->pluck('usage_count', 'sponsorship_id') ->toArray(); // 构建响应数组 $response = []; foreach ($sponsorshipItems as $item) { $usedCount = $usageCounts[$item->id] ?? 0; $remainingSpots = max($item->spots - $usedCount, 0); $response[$item->title] = $remainingSpots; } // 输出结果符合预期格式 dd($response);
关键说明
- 使用
whereIn批量查询,避免多次数据库请求,提升性能 keyBy('id')将查询结果转换为以ID为键的集合,方便快速匹配对应赞助项max($item->spots - $usedCount, 0)确保即使使用次数超出名额,剩余名额也显示为0,避免逻辑错误
内容的提问来源于stack exchange,提问作者smzapp
相关产品推荐
相关产品推荐

