时间段管理需动态配置时段并联动库存,订单状态流转须基于状态机与事件驱动,二者必须咬合以避免业务逻辑冲突。

ThinkPHP 搭建预约订餐系统时,时间段管理与订单状态流转是两个核心业务逻辑。关键不在于堆砌功能,而在于设计清晰、可扩展、易维护的数据结构和状态机机制。
时间段管理:按需切分 + 动态配置
预约订餐的时间段不能写死(如固定“11:00-11:30”),要支持商户自定义、节假日调整、库存联动:
-
数据库设计:单独建
time_slots表,字段含id、date(具体日期,支持单日配置)、start_time、end_time、max_orders、used_orders、status(1启用/0停用),避免用“全天分8个30分钟”硬编码 - 动态生成逻辑:在后台提供「批量生成」入口,选择日期范围+基础时段模板(如工作日 11:00–14:00 每30分钟一档),系统自动插入记录;节假日可单独编辑某天的时段或一键复制模板后微调
-
前端校验同步:用户选日期后,用 AJAX 请求
/api/slots?date=2024-06-15获取当日可用时段(已过滤满额、停用、过期的),返回带available: true/false和剩余名额的数组,禁用不可选项
订单状态流转:基于状态机 + 显式事件驱动
别用简单 status 字段(0待支付/1已接单/2已完成)硬编码判断,ThinkPHP 可借助行为(Behavior)或独立状态服务类实现可控流转:
-
定义合法状态与转移规则:例如「待支付 → 已取消」允许,但「已完成 → 已接单」禁止;用配置数组或数据库表
order_status_transitions管理,字段含from_status、to_status、trigger_event(如 'pay_success'、'admin_accept') -
统一状态变更入口:封装
OrderService::changeStatus($orderId, $event)方法,内部校验是否允许该转移、更新订单表、记录操作日志、触发后续动作(如发短信、减库存、通知骑手) -
避免并发冲突:关键操作(如用户支付成功更新状态)加数据库行锁:
Db::name('order')->where('id', $id)->where('status', 'wait_pay')->update(['status' => 'paid']),利用 WHERE 条件保证幂等性
关联场景处理:时段与订单状态联动
真实业务中二者必须咬合,否则会出现“时段已满却还能下单”或“取消订单后名额未释放”等问题:
立即学习“PHP免费学习笔记(深入)”;
-
下单时锁定时段名额:创建订单前先检查对应时段
used_orders ,通过事务完成「插入订单 + 更新 used_orders + 写入订单时段关联表」三步,任一失败则回滚 -
状态回退自动释放:当订单从「已接单」变为「已取消」或「支付超时」,触发回调自动执行
UPDATE time_slots SET used_orders = used_orders - 1 WHERE id = ? -
时段关闭前拦截:定时任务每5分钟扫描未来1小时内
status=0的时段,若used_orders > 0则禁止新下单,并给已下单用户推送提醒
状态和时段不是孤立模块,而是业务流的骨架。ThinkPHP 的模型事件(afterInsert、beforeUpdate)、命令行任务(php think timer:check_slots)、以及合理使用事务和乐观锁,能让这套逻辑既健壮又轻量。



















