Soft Deleted Entities

The soft deletion functionality can be achieved by applying a custom delete strategy in the mapper, combined with a global entity constrain to limit the selection.


You can alter the queueDelete method of the mapper and replace it with an Update command instead:

use Cycle\ORM\Mapper\Mapper;
use Cycle\ORM\Heap\Node;
use Cycle\ORM\Heap\State;
use Cycle\ORM\Command\CommandInterface;
use Cycle\ORM\Context\ConsumerInterface;
use Cycle\ORM\Command\Database\Update;

class SoftDeletedMapper extends Mapper
    public function queueDelete($entity, Node $node, State $state): CommandInterface
        // identify entity as being "deleted"

        $cmd = new Update(
            ['deleted_at' => new \DateTimeImmutable()]

        // forward primaryKey value from entity state
        // this sequence is only required if the entity is created and deleted 
        // within one transaction

        return $cmd;

You can permanently delete needed entities by using DBAL directly or by adding a switch to the mapper to fallback to the original command.

use Cycle\ORM\Heap;

// ...

public function queueDelete($entity, Heap\Node $node, Heap\State $state): \Cycle\ORM\Command\CommandInterface
    if ($state->getStatus() == Heap\Node::SCHEDULED_DELETE) {
        return parent::queueDelete($entity, $node, $state);

    // ...

Example usage:


$tr = new \Cycle\ORM\Transaction($orm);


To filter out deleted entities create the constraint:

use Cycle\ORM\Select;

class NotDeletedConstrain implements Select\ConstrainInterface
    public function apply(Select\QueryBuilder $query)
        $query->where('deleted_at', '=', null);


To enable soft deletes for your entity associate the newly created mapper and constrain with it:

/** @Entity(mapper="SoftDeletedMapper", constrain="NotDeletedConstrain") */
class User
    // ...

Now all entity deletes will issue Update commands instead.

Select Deleted

You can select deleted entities from the database by disabling your select constrain:

$userSelect = $orm->getRepository(User::class)->select();
Edit this page