You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

API Platform自定义过滤器:已交付商品数量范围筛选异常求助

问题分析

你当前的代码中,SIZE(' . $alias . '.items)统计的是主实体关联的全部商品总数,而非过滤出的已交付状态商品数量。后续的item.status = :status仅会过滤查询返回的关联商品记录,但并不会改变SIZE()函数的统计范围——它始终基于主实体关联的整个商品集合,而非筛选后的子集。

解决方案

下面提供两种可行的修正方案,你可以根据Doctrine版本和项目需求选择:

方案1:使用子查询统计已交付商品数量(兼容所有Doctrine版本)

通过子查询单独统计每个主实体下已交付状态的商品数量,再将这个统计值与数量范围比较:

protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void
{
    if ($property !== 'totalDeliveredItems' || empty($value)) {
        return;
    }

    $alias = $queryBuilder->getRootAliases()[0];
    $em = $queryBuilder->getEntityManager();
    $subQuery = $em->createQueryBuilder();

    // 替换以下两处为你的实际实体关联关系:
    // 1. 替换为商品实体的类名(如 OrderItem::class)
    // 2. 替换为商品实体关联主实体的字段名(如 i.order = :mainEntity)
    $subQuery->select('COUNT(i.id)')
        ->from('App\Entity\OrderItem', 'i')
        ->where('i.order = ' . $alias)
        ->andWhere('i.status = :status');

    $queryBuilder
        ->andWhere(sprintf('(%s) BETWEEN :from AND :to', $subQuery->getDQL()))
        ->setParameter('status', 'delivered')
        ->setParameter('from', 1)
        ->setParameter('to', 20);
}

方案2:使用Doctrine COUNT_FILTER函数(Doctrine ORM 2.13+ 可用)

如果你的项目使用Doctrine ORM 2.13及以上版本,可以直接使用COUNT_FILTER()函数,它支持对关联集合进行条件统计:

protected function filterProperty(string $property, $value, QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, Operation $operation = null, array $context = []): void
{
    if ($property !== 'totalDeliveredItems' || empty($value)) {
        return;
    }

    $alias = $queryBuilder->getRootAliases()[0];

    $queryBuilder
        ->andWhere("COUNT_FILTER($alias.items, 'status = :status') BETWEEN :from AND :to")
        ->setParameter('status', 'delivered')
        ->setParameter('from', 1)
        ->setParameter('to', 20);
}
额外说明
  • 移除原代码中的innerJoin($alias . '.items', 'item'):因为我们不需要返回关联的商品记录,只需要统计数量,这个关联会增加不必要的查询开销。
  • 原代码中的$queryBuilder->getQuery()->getResult();也可以移除:过滤器的职责是修改查询构造器,无需在这里执行查询,查询的执行由API平台的核心流程处理。

内容的提问来源于stack exchange,提问作者blueshark67

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 01:36:12