API Platform自定义过滤器如何实现OR及BETWEEN条件查询
实现方案
两种开发方式都可以满足需求,可根据逻辑的适用场景选择:
优先选择:自定义Filter实现(推荐)
你之前写自定义Filter只得到AND叠加的过滤效果,是因为默认调用andWhere()方法时,所有条件会被自动归到全局AND条件组下,只要手动构建OR条件分组即可实现需求,不需要依赖扩展开发,实现步骤如下:
- 新建自定义日期范围过滤器类,继承API Platform核心抽象Filter基类,约定前端传递FullCalendar当前视图的两个时间参数:
rangeStart(视图开始时间)、rangeEnd(视图结束时间) - 在过滤器的
apply方法中,手动通过Doctrine查询构造器的orX方法拼接跨字段OR条件,不要直接链式调用andWhere叠加两个字段的判断逻辑,核心代码参考:
public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void { // 校验请求中携带的时间范围参数,参数缺失时不触发过滤 if (!isset($context['filters']['rangeStart'], $context['filters']['rangeEnd'])) { return; } $rangeStart = new \DateTimeImmutable($context['filters']['rangeStart']); $rangeEnd = new \DateTimeImmutable($context['filters']['rangeEnd']); $startParamName = $queryNameGenerator->generateParameterName('rangeStart'); $endParamName = $queryNameGenerator->generateParameterName('rangeEnd'); // 手动构建OR条件组,匹配两个规则 $queryBuilder->andWhere( $queryBuilder->expr()->orX( // 规则1:startAt落在所选时间区间内 $queryBuilder->expr()->between('o.startAt', ":$startParamName", ":$endParamName"), // 规则2:endAt落在所选时间区间内 $queryBuilder->expr()->between('o.endAt', ":$startParamName", ":$endParamName") ) ) ->setParameter($startParamName, $rangeStart) ->setParameter($endParamName, $rangeEnd); }
- 将自定义过滤器注册为服务,在Event实体的配置中声明引入该过滤器后,前端请求事件列表接口时携带对应时间范围参数,即可拿到符合要求的事件数据。
备选方案:基于Doctrine Extension实现
如果该时间范围过滤是Event列表接口的默认强制逻辑,不需要前端传参触发(比如固定只返回当前可见范围内的事件),选择Extension开发更合适,实现逻辑和上述Filter内的查询拼接逻辑一致,只是逻辑触发时机从参数匹配变成了全局查询自动挂载。
注:内置DateFilter不支持跨字段OR条件拼接,所有过滤条件默认以AND逻辑叠加,没有相关配置入口可以调整该逻辑,不需要尝试修改内置过滤器适配需求。
内容的提问来源于stack exchange,提问作者Jules D.
相关产品推荐
相关产品推荐

