Symfony6+SonataAdmin4中,如何在过滤器应用后修改查询适配ULID?
Sonata Admin 4 兼容ULID模型过滤器的临时解决方法
方案1:自定义ULID兼容的ModelFilter(推荐)
针对单个过滤器做适配,无需全局修改:
- 创建自定义过滤器类,继承Sonata的ORM ModelFilter,在过滤逻辑中把字符串ULID转换为
Ulid对象:
<?php namespace App\Admin\Filter; use Sonata\DoctrineORMAdminBundle\Filter\ModelFilter; use Symfony\Component\Uid\Ulid; class UlidModelFilter extends ModelFilter { protected function filter($queryBuilder, $alias, $field, $data) { if (isset($data['value']) && is_string($data['value']) && Ulid::isValid($data['value'])) { $data['value'] = Ulid::fromString($data['value']); } return parent::filter($queryBuilder, $alias, $field, $data); } }
- 在Admin类的
configureDatagridFilters中,用自定义过滤器替换默认的ModelFilter:
use App\Admin\Filter\UlidModelFilter; protected function configureDatagridFilters(DatagridMapper $datagridMapper): void { $datagridMapper ->add('关联实体字段名', UlidModelFilter::class, [ 'label' => '关联实体', ]); }
方案2:全局监听Doctrine查询事件(批量处理)
如果所有实体ID都用ULID,可全局自动转换查询参数:
- 创建事件监听器,监听Doctrine的
preExecuteQuery事件,将字符串格式的ULID参数转为Ulid对象:
<?php namespace App\EventListener; use Doctrine\ORM\Event\PreExecuteQueryEventArgs; use Symfony\Component\Uid\Ulid; class UlidQueryParameterListener { public function preExecuteQuery(PreExecuteQueryEventArgs $args): void { foreach ($args->getQuery()->getParameters() as $parameter) { $value = $parameter->getValue(); if (is_string($value) && Ulid::isValid($value)) { $parameter->setValue(Ulid::fromString($value)); } } } }
- 在
config/services.yaml中注册监听器:
services: App\EventListener\UlidQueryParameterListener: tags: - { name: doctrine.event_listener, event: preExecuteQuery }
方案3:重写Admin类的参数处理逻辑(单Admin适配)
在目标Admin类中重写参数处理逻辑,提前转换ULID格式的过滤器参数:
use Sonata\AdminBundle\Datagrid\ProxyQueryInterface; protected function configureQuery(ProxyQueryInterface $query): ProxyQueryInterface { $query = parent::configureQuery($query); $filterParams = $this->getFilterParameters(); foreach ($filterParams as $key => $param) { if (isset($param['value']) && is_string($param['value']) && Ulid::isValid($param['value'])) { $filterParams[$key]['value'] = \Symfony\Component\Uid\Ulid::fromString($param['value']); } } $this->setFilterParameters($filterParams); return $query; }
以上方案均为官方兼容问题解决前的临时 workaround,无需自定义ModelManager。
内容的提问来源于stack exchange,提问作者Subsurf
相关产品推荐
相关产品推荐

