EasyAdmin中NumericFilter如何正确筛选字段为null的空值记录
问题根源
EasyAdmin 自带的 NumericFilter 没有对可空字段做兼容处理:当选择「等于」规则且输入框留空时,默认生成的SQL条件为 字段名 = '',而SQL语法中NULL值无法通过= ''或= null匹配,必须使用IS NULL才能命中字段为空的记录。
你之前的自定义实现存在两个错误:
- 先执行了通用等于逻辑生成
= ''的查询条件,后续追加的IS NULL条件和前者是AND关系,逻辑冲突导致永远返回空结果 - IS NULL语句仅写了表别名,没有指定具体字段名,生成的SQL本身存在语法问题
正确实现步骤
- 新建自定义可空数值过滤器,继承原生
NumericFilter,重写apply方法单独处理空值查询场景 - 在CRUD配置中把原生过滤器替换为自定义过滤器即可
<?php namespace App\Filter; use EasyCorp\Bundle\EasyAdminBundle\Filter\NumericFilter; use Doctrine\ORM\QueryBuilder; use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDataDto; use EasyCorp\Bundle\EasyAdminBundle\Filter\ComparisonType; class NullableNumericFilter extends NumericFilter { public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void { $alias = $filterDataDto->getEntityAlias(); $property = $filterDataDto->getProperty(); $comparison = $filterDataDto->getComparison(); $parameterName = $filterDataDto->getParameterName(); $parameter2Name = $filterDataDto->getParameter2Name(); $value = $filterDataDto->getValue(); $value2 = $filterDataDto->getValue2(); // 等于规则+输入为空时,直接查询字段为NULL的记录 if (ComparisonType::EQ === $comparison && ($value === '' || $value === null)) { $queryBuilder->andWhere(sprintf('%s.%s IS NULL', $alias, $property)); return; } // 区间查询走原有逻辑 if (ComparisonType::BETWEEN === $comparison) { $queryBuilder->andWhere(sprintf('%s.%s BETWEEN :%s AND :%s', $alias, $property, $parameterName, $parameter2Name)) ->setParameter($parameterName, $value) ->setParameter($parameter2Name, $value2); return; } // 其余比较规则(大于/小于/不等于等)走原有逻辑 $queryBuilder->andWhere(sprintf('%s.%s %s :%s', $alias, $property, $comparison, $parameterName)) ->setParameter($parameterName, $value); } }
过滤器替换
将原有字段配置中的原生数值过滤器替换为自定义过滤器:
// 替换前 // NumericFilter::new('shopSurface', 'shop_surface') // 替换后 NullableNumericFilter::new('shopSurface', 'shop_surface')
实现说明:
- 空值判断同时兼容输入值为
''字符串和null两种情况,覆盖不同表单提交场景的取值差异- 命中空值查询后直接终止后续逻辑,不会生成冲突的
= ''条件- 其余比较规则的逻辑和原生过滤器完全一致,不影响正常数值查询功能
内容的提问来源于stack exchange,提问作者tristan
相关产品推荐
相关产品推荐

