如何调整Doctrine查询逻辑实现返回指定日期可用的客房
核心实现逻辑
首先明确时间段重叠的统一判定规则:只要已有预订的开始时间 < 用户查询的离开时间 且 已有预订的离开时间 > 用户查询的开始时间,就说明该预订和用户的入住时段冲突,对应房间不可用。
我们最终要返回的是没有任何冲突预订的房间,包含完全没有预订记录的空房。
修正后的代码方案
方案1:LEFT JOIN写法(更简洁)
public function findByAvailableBookings($start, $leave) { $qb = $this->createQueryBuilder('r') ->leftJoin('r.bookings', 'b', 'WITH', 'b.startDate < :leaveDate AND b.leaveDate > :startDate') ->where('b.id IS NULL') ->setParameter('startDate', $start) ->setParameter('leaveDate', $leave); return $qb->getQuery()->getResult(); }
说明
通过左连接仅关联和用户查询时段冲突的预订,当连接出来的预订ID为空时,就说明该房间没有冲突预订,属于可用房间,同时会保留完全没有预订记录的空房。
方案2:NOT EXISTS写法(查询效率更高,大表场景更推荐)
public function findByAvailableBookings($start, $leave) { $qb = $this->createQueryBuilder('r'); $qb->where($qb->expr()->notExists( $qb->getEntityManager()->createQueryBuilder() ->select('b.id') ->from('App\Entity\Booking', 'b') // 此处替换为你自己的Booking实体命名空间 ->where('b.room = r.id') ->andWhere('b.startDate < :leaveDate') ->andWhere('b.leaveDate > :startDate') ->getDQL() )) ->setParameter('startDate', $start) ->setParameter('leaveDate', $leave); return $qb->getQuery()->getResult(); }
边界调整提示
如果你的业务规则不允许客人离开/入住日期重合(比如同一天不能有人退房又有人入住),把上述代码中的<、>替换为<=、>=即可。
内容的提问来源于stack exchange,提问作者Jojo l'artichaut
相关产品推荐
相关产品推荐

