【问题标题】:How to disable soft delete (Soft-deleteable) filter for doctrine in symfony如何在 symfony 中禁用学说的软删除(Soft-deleteable)过滤器
【发布时间】:2016-07-05 08:13:22
【问题描述】:

为 Doctrine 2 安装和使用 SoftDeleteable 行为扩展非常容易。问题通常是尝试为某些代码部分禁用它并再次启用。您可能希望这样做:

  1. 加载被软删除的实体
  2. 完全绕过软删除过滤器从数据库中删除实体

那么如何禁用呢?

【问题讨论】:

    标签: doctrine-orm symfony soft-delete


    【解决方案1】:

    1。如何加载软删除的实体

    根据文档,禁用实体管理器的过滤器:

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

    再次启用软删除:

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

    注意:如果实体已加载禁用软删除过滤器,则此行之前可能需要$em->clear();。

    2。如何从数据库中完全删除实体

    即使文档中没有提到,如果您需要删除实体并绕过软删除过滤器,第一个解决方案也不起作用。过滤器需要从实体管理器的事件监听器中移除:

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

    参考资料:

    【讨论】:

    • 过滤器只是一个原则查询,因此它与刷新过程没有真正的联系。一个更简单的硬删除方法是运行$em->remove($object); $em->flush($object); 两次。第一次刷新会将deletedAt 设置为现在。第二个会识别出deletedAt 之前已设置并且将忽略实际删除 - 你可以在这里看到github.com/Atlantic18/DoctrineExtensions/blob/master/lib/Gedmo/…。
    • @qooplmao 我用最新的标签(2.4.13)试过这个,但它不起作用。也许现在只有 master 分支。
    • @qooplmao 你的方法效果很好。我认为您应该将其发布为答案,因为我第一次最终忽略了它。 Aurelijus 的回答内容丰富,但最终没有必要。我用 v2.5.5 试过了。
    • 如果它不起作用,请尝试“soft-deleteable”而不是“softdeleteable”。所以应该是:$em->getFilters()->disable('soft-deleteable');
    【解决方案2】:

    您可以使用服务来禁用和重新启用软删除过滤器行为:

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

    用法:

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

    【讨论】:

      【解决方案3】:

      只是一个小小的提醒。

      当您想使用 Gedmo Softdeletable 硬删除实体时,您必须在相应的注释中包含 hardDelete=true,请参阅:

      @Gedmo\SoftDeleteable(fieldName="deletedAt", timeAware=false, hardDelete=true)

      编辑:hardDelete=true 默认为真

      有了这个,你不必禁用监听器/过滤器。如果你有hardDelete=false,上面建议的双重删除将不起作用。

      来源:

      【讨论】:

      • 然而hardDelete默认为真。
      【解决方案4】:

      正如qooplmao 在former comment 中发布的那样:一个简单且有效的解决方案是:

      // 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();
      

      刚刚再次发布它是为了给它一个小机器人更多的可见性,因为它就像一个魅力......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-04
        • 2016-06-25
        • 2015-02-28
        • 1970-01-01
        相关资源
        最近更新 更多