Reputation: 13446
I'm using SoftDeletable trait in entities from https://github.com/KnpLabs/DoctrineBehaviors/#softDeletable It's working fine, but sometimes I'd like to force delete the entity. How can I do that?
When I use $em->remove($entity)
, it gets soft-deleted but I need to remove it completely from the database.
Upvotes: 2
Views: 4561
Reputation: 5877
I have writte a service to disable and reenable the soft delete filter behaviour:
<?php
namespace App\Util;
use Doctrine\ORM\EntityManagerInterface;
use Gedmo\SoftDeleteable\SoftDeleteableListener;
class SoftDeleteFilter
{
/**
* @var string
*/
private $eventName;
/**
* @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 === 'onFlush') {
$this->eventName = $eventName;
$this->originalEventListener = $listener;
$em->getEventManager()->removeEventListener($eventName, $listener);
}
}
}
}
}
/**
* @param EntityManagerInterface $em
*/
public function undoRemoveSoftDeleteFilter(EntityManagerInterface $em)
{
if (empty($this->originalEventListener) || empty($this->eventName)) {
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($this->eventName, $this->originalEventListener);
}
}
usage:
$this->softDeleteFilter->removeSoftDeleteFilter($this->entityManager);
$this->entityManager->remove($issue);
$this->entityManager->flush();
$this->softDeleteFilter->undoRemoveSoftDeleteFilter($this->entityManager);
Upvotes: 1
Reputation: 154
I found simple solution. Entity will be softdeleted at first, but if it is already been soft deleted it will be hard deleted so my simple solution was:
$entity->setDeletedAt(new DateTime());
$entityManager->remove($entity);
$entityManager->flush();
Of course you need to disable 'softdelete' filter first and deletedAt is a sofdelete field.
Upvotes: 9
Reputation: 995
Since nifr's answer doesn't work anymore in the current version of the behaviors, I had a deeper look at the problem and got to that solution:
$em = $this->getDoctrine()->getManager();
// initiate an array for the removed listeners
$originalEventListeners = array();
// cycle through all registered event listeners
foreach ($em->getEventManager()->getListeners() as $eventName => $listeners) {
foreach ($listeners as $listener) {
if ($listener instanceof Knp\DoctrineBehaviors\ORM\SoftDeletable\SoftDeletableSubscriber) {
// 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($entity);
$em->flush();
// re-add the removed listener back to the event-manager
foreach ($originalEventListeners as $eventName => $listener) {
$em->getEventManager()->addEventListener($eventName, $listener);
}
See also https://stackoverflow.com/a/22838467/2564552
Upvotes: 1
Reputation: 52463
Just remove the subscriber from the EventManager
and add it back after the remove()
/ flush()
operation.
// get the event-manager
$eventManager = $this->get('doctrine')->getEventManager();
// get the listener
$subscriber = $this->get('knp.doctrine_behaviors.softdeletable_subscriber');
// remove the the subscriber for all events
$eventManager->removeEventListener($subscriber->getSubscribedEvents(), $subscriber);
// remove the entity
$em->remove($entity);
$em->flush();
// add it back to the event-manager
$eventManager->addEventSubscriber($subscriber);
Upvotes: 2