
在Doctrine中,当需要查询某个时间段内可用的产品,并且这些产品可能存在预订记录时,排除已被预订的时间段变得至关重要。核心问题在于如何有效地检测时间段的重叠,并利用QueryBuilder构建相应的SQL查询。
要检测时间段的重叠,需要考虑以下三种情况:
满足以上任何一个条件,都意味着预订与给定的时间段存在重叠。
以下是一个使用Doctrine QueryBuilder实现此逻辑的示例:
<?php
namespace App\Repository;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use App\Entity\Product;
use DateTimeInterface;
/**
* @extends ServiceEntityRepository<Product>
*
* @method Product|null find($id, $lockMode = null, $lockVersion = null)
* @method Product|null findOneBy(array $criteria, array $orderBy = null)
* @method Product[] findAll()
* @method Product[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ProductRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Product::class);
}
/**
* @return Product[] Returns an array of Product objects
*/
public function getAvailableProducts(\DateTimeInterface $startAt, \DateTimeInterface $endAt): array
{
$qb = $this->createQueryBuilder('p');
$qb->select('p')
->leftJoin('p.bookings', 'b')
->where(
$qb->expr()->not(
$qb->expr()->exists(
$this->createQueryBuilder('sub_p')
->select('1')
->from('App\Entity\Booking', 'sub_b')
->where('sub_b.product = p.id')
->andWhere(
$qb->expr()->orX(
$qb->expr()->between('sub_b.startAt', ':startAt', ':endAt'),
$qb->expr()->between('sub_b.endAt', ':startAt', ':endAt'),
$qb->expr()->andX(
$qb->expr()->lte('sub_b.startAt', ':startAt'),
$qb->expr()->gte('sub_b.endAt', ':endAt')
)
)
)
)
)
)
->setParameter('startAt', $startAt)
->setParameter('endAt', $endAt);
return $qb->getQuery()->getResult();
}
}代码解释:
注意事项:
总结:
通过使用 Doctrine QueryBuilder 和 NOT EXISTS 子查询,可以有效地排除在给定时间段内已被预订的产品。 这种方法能够准确地检测时间段的重叠,并返回符合条件的可用产品。
以上就是排除Doctrine QueryBuilder中重叠的时间段的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号