ApiPaltform - recuperar el artículo borrado suave

Estoy usando ApiPlatform y Symfony5

He implementado softdelete sobre una entidad User

Esta entidad se suaviza correctamente, todavía quiero mostrar los usuarios eliminados para algunos papeles, así que estoy tratando de DoctrineExtension para modificar la solicitud dinámicamente.

Aquí está mi 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'");
        }
    }

Verifiqué que entre en la condición.

Pero todavía tengo un 404 en el artículo que estoy tratando de recuperar (que todavía está en la base)

La misma solicitud entró en línea de comandos en el db devuelva el artículo que quiero recuperar.

También he intentado desactivar softdelete como sigue:

$this->entityManager->getFilters()->disable('softdeleteable');

Pero hacerlo tan deshabilitado para toda la aplicación, y no puedo volver a habilitarlo en la UserExtension

¿Alguien sabe lo que estoy haciendo mal? O si hay otra manera de recuperar objetos borrados suaves

O si tienes más doctores sobre el tema estaría agradecido porque me estoy quedando sin opciones

¡Gracias!

Pregunta hecha hace 3 años, 4 meses, 28 días - Por codechampionx


4 Respuestas:

  • Sí, no es sencillo, ya que tu consulta se ejecuta fuera de la extensión. Probablemente intentaría desactivar el filtro desletable suave para la entidad de usuario sólo en caso de que el usuario autenticado tenga el rol de Admin. Todavía sería deshabilitado después de la ejecución de la consulta, pero no debería causar demasiados efectos secundarios, ya que el usuario administrador debe ser capaz de ver entidades borradas del usuario. Algo así.

    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'");
        }
    }
    

    Respondida el Dec 18, 2020 a las 10:45 - por binarymaestro

    Votos positivos: 0 | Votos negativos: 0

  • Esta solución funcionó para mí, espero que funcione para quien caiga en esto:

    A través de un DataProvider es possbile a disable el filtro, consulta el objeto borrado suave que desea buscar y almacenarlo en una variable, entonces enable el filtro de nuevo y devolver su objeto.

    No sé si usar el a DataProvider de esta manera es una buena práctica, pero no ha creado efecto secundario en mi aplicación.

    Aquí hay un ejemplo:

        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;
        }
    

    Respondida el Dec 18, 2020 a las 10:52 - por markupmaestro

    Votos positivos: 0 | Votos negativos: 0

  • El problema que estás experimentando probablemente se deba a que estás intentando recuperar un artículo suavemente borrado mientras aún se aplica la lógica de eliminación suave en tus consultas.

    Aquí tienes algunas sugerencias que podrían ayudarte a resolver este problema:

    • Eliminar la condición de eliminación suave temporalmente: Puedes intentar eliminar temporalmente la condición de eliminación suave en tu UserExtension para ver si puedes acceder al artículo eliminado suavemente. Esto te permitirá verificar si el problema está relacionado con la lógica de eliminación suave.
    php
    public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = []): void
    {
        // Eliminar la condición de la eliminación suave temporalmente
        // $this->addWhere($queryBuilder, $resourceClass);
    }
    
    • Volver a habilitar el filtro softdeleteable: Si deshabilitaste el filtro `softdeleteable` a nivel de EntityManager y necesitas volver a habilitarlo solo para ciertas consultas, podrías intentar realizar esta acción dentro de tu UserExtension, antes de aplicar tu condición.
    php
    $this->entityManager->getFilters()->enable('softdeleteable');
    
    • Verificar el estado del artículo suavemente eliminado: Asegúrate de que el artículo que estás intentando recuperar realmente tiene un valor de `deletedAt` posterior a '2019-01-01'. Además, verifica que otros filtros o interceptores no estén interfiriendo con la recuperación del artículo eliminado suavemente.

    Espero que estas sugerencias te ayuden a encontrar una solución a tu problema. ¡Déjame saber si necesitas más ayuda o si tienes alguna otra pregunta!

    Respondida el Dec 19, 2020 a las 10:45 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • El problema es que cuando se elimina un elemento con soft delete, Doctrine marca el elemento como eliminado, pero no lo elimina de la base de datos. Esto significa que el elemento aún existe en la base de datos, pero no se puede recuperar utilizando métodos normales.

    Para recuperar un elemento eliminado temporalmente, debes utilizar el método findByTrashed() en el repositorio de Doctrine. Este método devolverá todos los elementos eliminados que coincidan con los criterios especificados.

    En tu caso, puedes utilizar el siguiente código para recuperar el usuario eliminado:

    php
    $user = $this->getDoctrine()
           
    • >getRepository(User::class)
    • >findByTrashed(['id' => $id]);

    Una vez que tengas el usuario, puedes restaurarlo utilizando el método restore(). Este método eliminará la marca de eliminación del usuario y lo hará visible nuevamente.

    Ten en cuenta que el método findByTrashed() solo está disponible si has habilitado el filtro de eliminación temporal en tu configuración de Doctrine. Puedes habilitar este filtro añadiendo la siguiente línea a tu archivo config/packages/doctrine.yaml:

    yaml
    doctrine:
        orm:
            filters:
                softdeleteable:
                    class: Gedmo\SoftDeleteable\Filter\SoftDeleteableFilter
    

    Una vez que hayas habilitado el filtro, podrás utilizar el método findByTrashed() para recuperar elementos eliminados temporalmente.

    Respondida el Dec 19, 2020 a las 10:50 - por Gemini

    Votos positivos: 0 | Votos negativos: 0