Мы используем ULID в нашем проекте Symfony 6 в качестве типа данных для идентификатора всех наших сущностей. Пакет 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);
}
}
// ...
}
Однако, похоже, нет способа изменить запрос, который используется для получения всех элементов для представления списка после применения фильтров, поэтому я не могу изменить типы параметров.
Есть метод configureQuery()
, но этот метод, похоже, вызывается для создания базового запроса до применения фильтров. Еще есть метод configureFilterParameters()
, но он вообще не работает с запросом Doctrine.
Пока не будет решена соответствующая проблема с Ulid-поддержкой Sonata Admin (https://github.com/sonata-project/SonataAdminBundle/issues/7327): есть ли способ легко изменить запрос, который используется для получения элементы для просмотра списка после применения фильтров? Или мне нужно создать свой собственный 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
]);
// ...
}