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

使用大于/小于/等于筛选时触发count()错误求助

问题分析

错误count(): Argument #1 ($value) must be of type Countable|array, Doctrine\ORM\Query\Expr\Andx given的核心原因是分页器(NewPaginator)在处理带GROUP BY和HAVING的查询时,错误地将Doctrine的查询表达式对象(Andx)传入了count()函数,而非可计数的结果集。

从代码逻辑来看,当你添加GROUP BY s.id和HAVING条件后,默认的分页计数逻辑无法正确解析这种分组查询结构,最终触发类型错误。

解决方案

1. 手动构建分页计数查询

修改findPaginated方法,为NewPaginator提供手动构建的count查询,绕过默认计数逻辑的缺陷:

public function findPaginated(InterpretationTranslationSourceFilter $filter): NewPaginator
{
    $qb = $this->createQueryBuilder('s')
        ->leftJoin('s.authorToSourceRelations', 'atsr')
        ->select('s as interpretationTranslationSource')
        ->addSelect('COUNT(DISTINCT atsr.id) AS authorToSourceRelationsCount')
        ->groupBy('s.id');

    // 原有筛选条件逻辑保留
    if ($filter->isHasLink() OR $filter->getDontHasLink()) {
        if ($filter->isHasLink()) {
            $qb->andWhere('s.url IS NOT NULL');
        }

        if ($filter->getDontHasLink()) {
            $qb->andWhere('s.url IS NULL');
        }
    }

    if ($filter->getSortByAuthorsCount()) {
        $comparisonOperator = substr($filter->getSortByAuthorsCount(), 0, 1);
        $authorsCount = (int) substr($filter->getSortByAuthorsCount(), 1);

        switch ($comparisonOperator) {
            case '=':
                $qb->having('authorToSourceRelationsCount = :authorsCount')
                    ->setParameter('authorsCount', $authorsCount);
                break;
            case '>':
                $qb->having('authorToSourceRelationsCount > :authorsCount')
                    ->setParameter('authorsCount', $authorsCount);
                break;
            case '<':
                $qb->having('authorToSourceRelationsCount < :authorsCount')
                    ->setParameter('authorsCount', $authorsCount);
                break;
            default:
                $qb->orderBy('s.title', 'ASC');
                break;
        }
    }

    if ($filter->getTitle()) {
        $qb->andWhere('s.title like :title')
            ->setParameter('title', '%' . $filter->getTitle() . '%');
    }

    if ($filter->getUrl()) {
        $qb->andWhere('s.url LIKE :url')
            ->setParameter('url', '%' . $filter->getUrl() . '%');
    }

    // 手动构建count查询
    $countQb = $this->createQueryBuilder('s')
        ->select('COUNT(DISTINCT s.id)')
        ->leftJoin('s.authorToSourceRelations', 'atsr');
    
    // 复制主查询的WHERE条件
    foreach ($qb->getDQLPart('where') as $wherePart) {
        $countQb->andWhere($wherePart);
    }
    
    // 复制主查询的HAVING条件(分组筛选需保留)
    if ($qb->getDQLPart('having')) {
        foreach ($qb->getDQLPart('having') as $havingPart) {
            $countQb->having($havingPart);
        }
    }
    
    // 同步参数绑定
    foreach ($qb->getParameters() as $param) {
        $countQb->setParameter($param->getName(), $param->getValue());
    }
    
    // 将count查询传入分页器(需确保NewPaginator支持此方法)
    $paginator = new NewPaginator($qb, $filter);
    $paginator->setCountQuery($countQb);

    return $paginator;
}

2. 适配NewPaginator实现

如果你的NewPaginator没有setCountQuery方法,需要修改其内部逻辑:

  • 移除直接对主查询调用count()的逻辑,改为单独执行手动构建的count查询获取总条数。
  • 针对分组查询,确保count查询统计的是分组后的主键数量,而非原始行数。

3. 输入合法性校验(可选优化)

在处理$filter->getSortByAuthorsCount()时,添加格式校验,避免非法输入引发异常:

if ($filter->getSortByAuthorsCount()) {
    $sortValue = $filter->getSortByAuthorsCount();
    // 校验格式:首字符为=/>/<,后续为数字
    if (!preg_match('/^[=><]\d+$/', $sortValue)) {
        $qb->orderBy('s.title', 'ASC');
        goto endSortLogic; // 或用return/continue跳过后续逻辑
    }
    
    $comparisonOperator = substr($sortValue, 0, 1);
    $authorsCount = (int) substr($sortValue, 1);
    
    // 原有switch逻辑...
}
endSortLogic:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:06:10