多选模式下EntityFilter不等于筛选结果异常问题咨询
问题诱因
EasyAdmin原生EntityFilter组件在处理多值关联字段的否定匹配规则时存在底层SQL生成逻辑缺陷:
- 单选场景下,每条数据只会关联一个选项,默认生成的
左连接 + 关联ID != 目标值逻辑可以正常运行 - 多选场景下,只要某条数据关联的任意一个选项不符合排除值,就会被判定为匹配结果,哪怕这条数据同时关联了你要排除的选项,最终就会出现明明绑定了James Harveyd的记录仍然出现在「不等于James Harveyd」筛选结果里的问题。
修复方案
你可以选择以下任意一种方案解决问题:
- 自定义修正版EntityFilter,替换原生组件
继承原生EntityFilter类,重写条件应用逻辑,否定匹配场景下改用NOT EXISTS子查询实现正确的排除逻辑,代码示例:
替换原筛选配置中的类名即可生效:<?php namespace App\Filter; use Doctrine\ORM\QueryBuilder; use EasyCorp\Bundle\EasyAdminBundle\Filter\EntityFilter; use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDataDto; class MultiCompatibleEntityFilter extends EntityFilter { public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void { $comparison = $filterDataDto->getComparison(); $paramName = $filterDataDto->getParameterName(); $rootAlias = $queryBuilder->getRootAliases()[0]; $property = $filterDataDto->getProperty(); // 针对否定匹配规则走修正后的逻辑 if (in_array($comparison, ['!=', 'NOT IN'])) { $subDql = $queryBuilder->getEntityManager()->createQueryBuilder() ->select('1') ->from($filterDataDto->getEntityClass(), 'root') ->leftJoin("root.$property", 'assoc') ->where("root.id = $rootAlias.id") ->andWhere("assoc.id IN (:$paramName)") ->getDQL(); $queryBuilder->andWhere("NOT EXISTS ($subDql)") ->setParameter($paramName, $filterDataDto->getValue()); return; } // 其余匹配规则沿用原生逻辑 parent::apply($queryBuilder, $filterDataDto, $fieldDto, $entityDto); } }public function configureFilters(Filters $filters): Filters { return $filters ->add(MultiCompatibleEntityFilter::new('supervisors', 'supervisors')); } - 改用ChoiceFilter手动实现筛选逻辑
如果不想自定义过滤器类,可以直接使用ChoiceFilter,手动加载supervisor选项列表,自行编写查询匹配逻辑,避开原生EntityFilter的逻辑缺陷。
内容的提问来源于stack exchange,提问作者tristan
相关产品推荐
相关产品推荐

