Я использую ApiPlatform
и Symfony5
Я реализовал softdelete
на объекте User
Этот объект удален правильно, я все еще хочу отображать удаленных пользователей для некоторых ролей, поэтому я пытаюсь DoctrineExtension
динамически изменить запрос.
Вот мой UserExtension.php
:
public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
{
$this->addWhere($queryBuilder, $resourceClass);
}
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
{
if (User::class == $resourceClass &&
$this->security->isGranted(GenericRoles::ROLE_ADMIN)
) {
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder->andWhere("$rootAlias.deletedAt > '2019-01-01'");
}
}
Я проверил, что вхожу в условие if.
Но я все еще получаю 404
за предмет, который пытаюсь восстановить (который все еще находится в базе)
Тот же запрос, введенный в командной строке в базе данных, возвращает мне элемент, который я хочу восстановить.
Я также пытался отключить softdelete
следующим образом:
$this->entityManager->getFilters()->disable('softdeleteable');
Но при этом отключите его для всего приложения, и я не могу снова включить его в UserExtension
Кто-нибудь знает, что я делаю неправильно? Или если есть другой способ восстановить обратимо удаленные элементы
Или, если у вас есть больше документов по этому вопросу, я был бы признателен, потому что у меня заканчиваются варианты.
Спасибо!
Да, это не просто, так как ваш запрос выполняется вне расширения. Я бы, вероятно, попытался отключить мягко удаляемый фильтр для объекта пользователя только в том случае, если аутентифицированный пользователь имеет роль администратора. Он по-прежнему будет отключен после выполнения запроса, но это не должно вызывать слишком много побочных эффектов, поскольку пользователь с правами администратора должен иметь возможность видеть удаленные объекты пользователя. Что-то вроде этого.
public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
{
$this->addWhere($queryBuilder, $resourceClass);
}
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
{
if (User::class === $resourceClass &&
$this->security->isGranted(GenericRoles::ROLE_ADMIN)
) {
$filter = $this->entityManager->getFilters()->enable('softdeleteable');
$filter->disableForEntity(User::class);
$rootAlias = $queryBuilder->getRootAliases()[0];
$queryBuilder->andWhere("$rootAlias.deletedAt > '2019-01-01'");
}
}
Это решение сработало для меня, я надеюсь, что оно сработает для тех, кто попадется на это:
С помощью DataProvider
можно disable
фильтровать, запрашивать мягко удаленный объект, который вы хотите запросить, и сохранять его в переменной, затем enable
снова фильтровать и возвращать ваш объект.
Я не знаю, является ли использование DataProvider
таким образом хорошей практикой, но это не создало побочных эффектов в моем приложении.
Вот пример:
public function getItem(string $resourceClass, $id, string $operationName = null, array $context = [])
{
if ($this->security->isGranted(GenericRoles::ROLE_ADMIN))
) {
$this->entityManager->getFilters()->disable('softdeleteable');
}
$softDeletedObject = $this->itemDataProvider->getItem($resourceClass, $id, $operationName, $context);
$this->entityManager->getFilters()->enable('softdeleteable');
return $softDeletedObject;
}
Спасибо за ваш комментарий! Я не пробовал это решение, но с помощью
DataProvider
я могуdisable
фильтр запросить объект, который я хочу запросить, а затем сноваenable
фильтр, возвращая интересующий объект.