web-dev-qa-db-fra.com

Comment supprimer le filtre de suppression logicielle (Symphony)

L'installation et l'utilisation de l'extension de comportement SoftDeleteable pour Doctrine 2 est assez simple. Le problème est généralement d'essayer de le désactiver pour certaines parties de code et de l'activer à nouveau. Vous voudrez peut-être faire ceci pour:

  1. entité de chargement supprimée de manière logicielle
  2. supprimer l'entité de la base de données en contournant entièrement le filtre de suppression logicielle

Alors, comment le désactiver?

9
Aurelijus Rozenas

1. Comment charger une entité supprimée logiquement

Selon la documentation, désactivez le filtre pour le gestionnaire d'entités:

$em->getFilters()->disable('softdeleteable');
$object = $em->find('AppBundle:Object', 1); // soft-deleted entity will be loaded

Pour activer à nouveau la suppression logicielle:

$em->getFilters()->enable('softdeleteable');

Remarque: $em->clear(); peut être requis avant cette ligne, si l'entité était déjà chargée avec le filtre de suppression progressive désactivé.

2. Comment supprimer l'entité de la base de données entièrement

Bien que cela ne soit pas mentionné dans la documentation, la première solution ne fonctionne pas si vous devez supprimer une entité et contourner le filtre de suppression progressive. Le filtre doit être supprimé des écouteurs d'événements du gestionnaire d'entités:

// initiate an array for the removed listeners
$originalEventListeners = [];

// cycle through all registered event listeners
foreach ($em->getEventManager()->getListeners() as $eventName => $listeners) {
    foreach ($listeners as $listener) {
        if ($listener instanceof \Gedmo\SoftDeleteable\SoftDeleteableListener) {

            // store the event listener, that gets removed
            $originalEventListeners[$eventName] = $listener;

            // remove the SoftDeletableSubscriber event listener
            $em->getEventManager()->removeEventListener($eventName, $listener);
        }
    }
}

// remove the entity
$em->remove($object);
$em->flush($object); // or $em->flush();

// re-add the removed listener back to the event-manager
foreach ($originalEventListeners as $eventName => $listener) {
    $em->getEventManager()->addEventListener($eventName, $listener);
}

Références:

20
Aurelijus Rozenas

Vous pouvez utiliser un service pour désactiver et réactiver le comportement du filtre de suppression logicielle:

<?php

namespace App\Util;

use Doctrine\ORM\EntityManagerInterface;
use Gedmo\SoftDeleteable\SoftDeleteableListener;

class SoftDeleteFilter
{
    /**
     * @var string
     */
    const EVENT_NAME = 'onFlush';

    /**
     * @var object
     */
    private $originalEventListener;

    /**
     * @param EntityManagerInterface $em
     */
    public function removeSoftDeleteFilter(EntityManagerInterface $em)
    {
        foreach ($em->getEventManager()->getListeners() as $eventName => $listeners) {
            foreach ($listeners as $listener) {
                if ($listener instanceof SoftDeleteableListener) {
                    if ($eventName === self::EVENT_NAME) {
                        $this->originalEventListener = $listener;
                        $em->getEventManager()->removeEventListener($eventName, $listener);
                    }
                }
            }
        }
    }

    /**
     * @param EntityManagerInterface $em
     */
    public function undoRemoveSoftDeleteFilter(EntityManagerInterface $em)
    {
        if (empty($this->originalEventListener)) {
            throw new \Exception('can not undo remove, soft delete listener was not removed');
        }
        // re-add the removed listener back to the event-manager
        $em->getEventManager()->addEventListener(self::EVENT_NAME, $this->originalEventListener);
    }
}

usage:

$this->softDeleteFilter->removeSoftDeleteFilter($this->entityManager);
$this->entityManager->remove($entity);
$this->entityManager->flush();
$this->softDeleteFilter->undoRemoveSoftDeleteFilter($this->entityManager);
1

Comme dans un commentaire précédent de qooplmao posted: Une solution simple et efficace est:

// Remove an entity entirely from the DB (skip soft delete)
$this->entityManager->remove($entity);
$this->entityManager->flush();
// Just run it a second time :-)
$this->entityManager->remove($entity);
$this->entityManager->flush();

Je viens de le poster à nouveau pour lui donner un peu plus de visibilité car il fonctionne comme un charme ...

0