Измените запрос, который используется для получения элементов списка после применения фильтра

Мы используем 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 и еще что-то?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
0
0
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я обнаружил, что довольно легко использовать 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
    ]);
    // ...
}

Другие вопросы по теме