我们在 Symfony 6 项目中使用 ULID 作为我们所有实体 ID 的数据类型。
symfony/uid
包对此有很大帮助。为了快速构建管理界面,我们使用 Sonata Admin 4。
不幸的是,截至目前,Sonata Admin 与 ULID 完全不兼容。这会影响列表视图的实体/模型过滤器:过滤器字段正确显示您可以过滤的所有可用实体,但过滤器未正确应用,因为作为生成的 Doctrine 查询中的参数类型,默认数据类型
string
被用来代替Ulid
.
以下代码导致显示一个选择字段,显示所有可用的相关实体,但生成的查询使用所选实体的 ULID 作为字符串而不是二进制值,这导致查询结果为空。
protected function configureDatagridFilters(DatagridMapper $datagrid): void
{
$datagrid->add('subject.relatedEntity', ModelFilter::class);
// ...
}
在自定义控制器方法的上下文中,我找到了一种使用以下方法更改查询参数类型的方法:
public function myCustomControllerAction(
ProxyQueryInterface $query,
AdminInterface $admin
): Response {
// Find all parameters that are referencing an 'id' property
// and change their type to the UlidType of the symfony/uid package
foreach ($query->getQueryBuilder()->getParameters() as $parameter) {
if (stripos($parameter->getName(), '_id_') !== false) {
$parameter->setValue($parameter->getValue(), UlidType::NAME);
}
}
// ...
}
但是,似乎没有办法修改用于获取列表视图的所有项目的查询after应用了过滤器,因此我无法更改参数类型。
有方法
configureQuery()
,但是这个方法似乎被调用来创建基本查询,before应用过滤器。还有方法configureFilterParameters()
,但是这个方法根本不适用于Doctrine查询。
直到有关 Sonata Admin 的 Ulid 支持的相应问题得到解决(https://github.com/sonata-project/SonataAdminBundle/issues/7327):是否有一种方法可以轻松更改用于获取的查询列表视图的项目after应用过滤器?还是我必须创建自己的
ModelManager
之类的东西?
我发现将
CallbackFilter
与 EntityType
表单域一起使用非常容易,所以我刚刚创建了一个自定义过滤器,它可能没有内置的 ModelFilter
那样灵活,但它做的工作:
protected function configureDatagridFilters(DatagridMapper $datagrid): void
{
$datagrid->add('subject.relatedEntity', CallbackFilter::class, [
'callback' => function(ProxyQueryInterface $query, string $alias, string $field, FilterData $data): bool {
if (!$data->hasValue()) {
return false;
}
$qb = $query->getQueryBuilder();
$qb->andWhere(
sprintf(
'IDENTITY(%s.%s) = :custom_related_entity_filter_selected_id',
$alias,
$field
)
);
$qb->setParameter(':custom_related_entity_filter_selected_id', $data->getValue()->getId(), UlidType::NAME);
return true;
},
'field_type' => EntityType::class
]);
// ...
}