
本文详解如何为多个房间分别计算一组选定日期的总价格——对每个日期,优先使用 `options` 中匹配的特定价格,未匹配则 fallback 到 `default_price`,并汇总得出各房间的 `total_price`。
在酒店预订、会议室租赁等场景中,常需根据用户选择的连续日期(如入住/退房区间),动态计算不同房型的总费用。关键逻辑在于:每个日期单独判断价格来源——若该日期在房间的 options 数组中存在明确配置,则采用对应 price;否则统一使用 default_price。最终将所有选中日期的价格相加,即为该房间的 total_price。
以下是一个简洁、可读性强且无副作用的实现方案(兼容 php 7.4+):
$selectedDates = ['10-04-2022', '11-04-2022', '12-04-2022']; $setRooms = [ [ 'id' => 1, 'title' => 'Room1', 'default_price' => 50, 'options' => [ ['date' => '12-04-2022', 'price' => 100], ['date' => '13-04-2022', 'price' => 200], ['date' => '14-04-2022', 'price' => 200], ] ], [ 'id' => 2, 'title' => 'Room2', 'default_price' => 120, 'options' => [ ['date' => '11-04-2022', 'price' => 200], ['date' => '12-04-2022', 'price' => 300], ['date' => '13-04-2022', 'price' => 400], ] ], ]; $result = []; foreach ($setRooms as $room) { $total = 0; foreach ($selectedDates as $date) { // 精确匹配 date 字段(字符串相等,避免 Carbon 解析开销) $matchedOptions = array_filter($room['options'], fn($opt) => $opt['date'] === $date); if (count($matchedOptions) === 1) { $total += current($matchedOptions)['price']; } else { $total += $room['default_price']; } } $result[] = [ 'id' => $room['id'], 'title' => $room['title'], 'total_price' => $total ]; } print_r($result);
✅ 输出结果:
Array ( [0] => Array ( [id] => 1 [title] => Room1 [total_price] => 200 // 50 + 50 + 100 ) [1] => Array ( [id] => 2 [title] => Room2 [total_price] => 620 // 120 + 200 + 300 ) )
⚠️ 关键注意事项:
- 勿复用累加变量:原始代码中 $price 在外层循环外定义,导致房间间价格相互污染。务必为每个房间重置 $total = 0。
- 避免日期格式转换开销:示例中直接使用字符串比对(===),前提是输入日期格式严格统一(如 ‘d-m-Y’)。若需兼容多种格式(如 ‘Y-m-d’),再引入 carbon::parse() 并标准化格式。
- array_filter + current() 更安全:相比手动遍历或 array_key_first(),current() 可安全获取首个匹配项(即使键非数字),且语义清晰。
- 性能提示:若 options 数量极大(>1000 条),建议预先构建 date → price 的哈希映射(如 array_column($room[‘options’], ‘price’, ‘date’)),将单次查找从 O(n) 优化至 O(1)。
该方案结构清晰、无外部依赖、易于单元测试,适用于 laravel、symfony 或纯 PHP 项目。