0

Softdeleteable doctrine フィルターを使用していますが、データベースからすべてのレコードを削除する方法があり、レコードを削除する前にフィルターを無効にする必要があります。ただし、実行されるたびにのみ機能するようです(レコードにdeletedAt値がある場合)。

<?php
/**
 * Created by PhpStorm.
 * User: toby
 * Date: 08/07/2014
 * Time: 17:29
 */

namespace Client\ComponentBundle\Entity;


use Doctrine\ORM\EntityRepository;

abstract class BaseEntityRepository extends EntityRepository
{
    /**
     * Attempts to delete all records from a table
     *
     * @param bool $bypassSoftDelete
     *
     * @return bool
     */
    public function deleteAll( $bypassSoftDelete = false )
    {
        $softdeleteableFilter = 'softdeleteable';
        $filters              = $this->getEntityManager()->getFilters();

        if ($bypassSoftDelete && $filters->isEnabled( $softdeleteableFilter )) {
            $filters->disable( $softdeleteableFilter );
        }

        $entities = $this->findAll();
        foreach ($entities as $entity) {
            $this->getEntityManager()->remove( $entity );
        }

        $this->getEntityManager()->flush();

        if ($bypassSoftDelete) {
            $this->getEntityManager()->getFilters()->enable( $softdeleteableFilter );
        }
    }
}

なぜこれが当てはまるのか誰にも分かりますか?

4

1 に答える 1

1

私の知る限り、softdeleteable フィルターは、選択のクエリに何かを追加するだけなので、削除する前にそれを有効または無効にしても、実際には何もしません。

何かを削除するために 2 回の試行を行う必要があるのは、このためです...

Gedmo\SoftDeleteable\SoftDeleteableListener

/**
 * If it's a SoftDeleteable object, update the "deletedAt" field
 * and skip the removal of the object
 *
 * @param EventArgs $args
 * @return void
 */
public function onFlush(EventArgs $args)
{
    //...

    //getScheduledDocumentDeletions
    foreach ($ea->getScheduledObjectDeletions($uow) as $object) {
        //...

        if (isset($config['softDeleteable']) && $config['softDeleteable']) {

            $reflProp = $meta->getReflectionProperty($config['fieldName']);
            $oldValue = $reflProp->getValue($object);

            <!-- THIS BIT -->
            if ($oldValue instanceof \Datetime) {
                continue; // want to hard delete
            }

            //...
        }
    }
}

オブジェクトが実際に削除されるかどうかを決定する唯一のことは、それが以前に「softdeleted」されているかどうかです。これは、フィルターで何をしても、リスナーは最初にソフト削除を行い、次に次のパスでハード削除を行うことを意味します。

これを回避する最も簡単な方法はdeletedAt、実際の削除をフラッシュする前に、(または deletedAt フィールド) の日付を設定することだと思います。

追加情報

ORM は、UPDATE に置き換えられる DELETE 操作を直接実行しません。

モデルを削除すると、ORM によって削除がスケジュールされます。これはリスナーによって傍受され、更新された deletedAt フィールド セットで再び永続化されます。

fieldNameあなたがに設定されていると仮定しますdeletedAt

Gedmo\SoftDeleteable\SoftDeleteableListener

public function onFlush(EventArgs $args)
{
    //..

    // Get all entities that are scheduled for deletion
    foreach ($ea->getScheduledObjectDeletions($uow) as $object) {
        // Check softdeleteable is enabled for model
        if (isset($config['softDeleteable']) && $config['softDeleteable']) {
            // Get current value of deletedAt
            $reflProp = $meta->getReflectionProperty($config['fieldName']);
            $oldValue = $reflProp->getValue($object);

            // If deletedAt is already set, drop out of update process,
            // otherwise continue on with "softdelete"
            if ($oldValue instanceof \Datetime) {
                continue; // want to hard delete
            }

            // Dispatch "PRE_SOFT_DELETE" event
            $evm->dispatchEvent(
                self::PRE_SOFT_DELETE,
                $ea->createLifecycleEventArgsInstance($object, $om)
            );

            // Set deletedAt field to now
            $date = new \DateTime();
            $reflProp->setValue($object, $date);

            // Persist model and schedule for extra update, moving 
            // model from "scheduledForDeletion" to "scheduledForUpdate"
            $om->persist($object);
            $uow->propertyChanged($object, $config['fieldName'], $oldValue, $date);
            $uow->scheduleExtraUpdate($object, array(
                $config['fieldName'] => array($oldValue, $date)
            ));

            // Dispatch "POST_SOFT_DELETE" event
            $evm->dispatchEvent(
                self::POST_SOFT_DELETE,
                $ea->createLifecycleEventArgsInstance($object, $om)
            );
        }
    }
}
于 2014-08-22T08:43:25.717 に答える