
本文详解如何在多会议室预约系统中精准检测时间冲突,避免跨房间误判,并修正传统时间重叠逻辑缺陷,同时防范sql注入风险。
本文详解如何在多会议室预约系统中精准检测时间冲突,避免跨房间误判,并修正传统时间重叠逻辑缺陷,同时防范sql注入风险。
在构建多会议室(如 assembly_hall)共享调度系统时,一个常见但极易出错的逻辑是:仅校验时间是否重叠,却忽略空间维度(即房间ID)。原始代码中的冲突查询未限定 assembly_hall_id,导致“A房间10:00–12:00”与“B房间同时间段”的预约被错误拒绝——这显然违背业务需求:不同房间的时间资源应相互独立。
更关键的是,原始冲突判断逻辑存在根本性缺陷:
('{$d_start}' BETWEEN unix_timestamp(datetime_start) AND unix_timestamp(datetime_end))
OR ('{$d_end}' BETWEEN unix_timestamp(datetime_start) AND unix_timestamp(datetime_end))
该逻辑只能捕获“新时段的起点或终点落在已有时段内”的情况,却遗漏了两种典型重叠:
- 新时段完全包裹旧时段(如旧:13:00–14:00,新:12:00–15:00)
- 旧时段完全包裹新时段(如旧:12:00–15:00,新:13:00–14:00)
✅ 正确的区间重叠判定公式(适用于任意两个闭区间 [a,b] 和 [c,d])为:MAX(a, c)
即:两区间交集非空 ⇔ 较大起点
结合本场景(需同时满足:同一房间 + 时间重叠),修正后的查询应如下:
// 安全化处理:使用预处理语句(强烈推荐)
$d_start = strtotime($datetime_start);
$d_end = strtotime($datetime_end);
// 构建参数化查询(防SQL注入)
$stmt = $this->conn->prepare("
SELECT COUNT(*) FROM `schedule_list`
WHERE assembly_hall_id = ?
AND ? datetime_start
" . ($id > 0 ? " AND id != ?" : "")
);
if ($id > 0) {
$stmt->bind_param("iisi", $assembly_hall_id, $d_start, $d_end, $id);
} else {
$stmt->bind_param("iis", $assembly_hall_id, $d_start, $d_end);
}
$stmt->execute();
$chk = $stmt->get_result()->fetch_row()[0];
$stmt->close();
? 关键说明:
-
datetime_start/datetime_end字段应为DATETIME类型(非Unix时间戳),直接参与比较更高效、可读性更强; - 条件
? datetime_start等价于LEAST(datetime_end, ?) > GREATEST(datetime_start, ?),是标准重叠判据的简洁写法; -
assembly_hall_id必须作为WHERE条件强制过滤,确保只比对同一房间的历史记录; -
绝对禁止拼接SQL字符串(如原代码
$data.=" {$k} = '{$v}'"),所有用户输入必须通过预处理绑定。
此外,建议在数据库层增加约束增强健壮性:
-- 在 schedule_list 表上添加复合索引,加速冲突查询 CREATE INDEX idx_hall_time ON schedule_list (assembly_hall_id, datetime_start, datetime_end);
最后,在业务逻辑中,务必确保前端提交的 assembly_hall_id 已被校验合法性(如存在于 assembly_hall 表),并明确传递该值——这是实现“房间隔离”的前提。完整修正后,系统将精准识别:同一房间内任意形式的时间重叠(包含、相交、边界接触),而不同房间的预约互不影响,真正实现多资源并发调度的可靠性。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











