Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mongodb Odm Softdelete Bundle Laravel Package

doctrine/mongodb-odm-softdelete-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    • Add the bundle to appKernel.php (Symfony 2.0.x only).
    • Configure deleted_field_name in config.yml (e.g., deletedAt).
    • Ensure Doctrine\ODM\MongoDB\SoftDelete is autoloaded.
  2. First Use Case:

    • Annotate a document with @SoftDelete:
      use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
      use Doctrine\ODM\MongoDB\SoftDelete\SoftDelete;
      
      /**
       * @MongoDB\Document
       * @SoftDelete
       */
      class User {}
      
    • Soft-delete a record:
      $user = $dm->getRepository('AppBundle:User')->find(1);
      $user->delete(); // Triggers soft-delete (sets `deletedAt` to current timestamp)
      
    • Query soft-deleted records:
      $dm->getRepository('AppBundle:User')->findAll(); // Excludes soft-deleted by default
      $dm->getRepository('AppBundle:User')->findAllWithDeleted(); // Includes soft-deleted
      

Implementation Patterns

Common Workflows

  1. Soft-Deletion in Controllers:

    // Soft-delete a user
    $user = $dm->find('AppBundle:User', $id);
    $user->delete(); // Sets `deletedAt` without removing from DB
    $dm->flush();
    
    // Restore a soft-deleted user
    $user = $dm->getRepository('AppBundle:User')->findWithDeleted($id);
    $user->setDeletedAt(null); // Explicitly restore
    $dm->flush();
    
  2. Querying with Soft-Deletes:

    • Exclude soft-deleted (default):
      $users = $dm->getRepository('AppBundle:User')->findAll();
      
    • Include soft-deleted:
      $users = $dm->getRepository('AppBundle:User')->findAllWithDeleted();
      
    • Custom queries:
      $query = $dm->createQueryBuilder('AppBundle:User')
          ->field('deletedAt')->equals(null) // Explicitly filter
          ->getQuery();
      
  3. Bulk Soft-Deletion:

    $users = $dm->getRepository('AppBundle:User')->findBy(['active' => true]);
    foreach ($users as $user) {
        $user->delete();
    }
    $dm->flush();
    
  4. Event Listeners:

    • Trigger actions on soft-delete:
      // In a service or listener
      $user->addPreDeleteListener(function ($user) {
          // Log or send notifications before soft-delete
      });
      

Integration Tips

  • Symfony Forms:

    • Use SoftDelete with DataTransformer to handle soft-deletion in forms.
    • Example:
      $form->add('softDelete', CheckboxType::class, [
          'mapped' => false,
          'label' => 'Soft Delete',
      ]);
      
      Then manually handle the soft-delete logic in the form submit handler.
  • APIs:

    • Return soft-deleted records with a deleted flag:
      $user = $dm->getRepository('AppBundle:User')->findWithDeleted($id);
      $data = [
          'id' => $user->getId(),
          'deleted' => $user->getDeletedAt() !== null,
      ];
      
  • Testing:

    • Mock soft-deletion in unit tests:
      $user = new User();
      $user->delete(); // Simulate soft-delete
      $this->assertNotNull($user->getDeletedAt());
      

Gotchas and Tips

Pitfalls

  1. Symfony 2.0.x Only:

    • This bundle is archived and only supports Symfony 2.0.x. Avoid using it in newer Symfony versions (use alternatives like stof/doctrine-extensions-bundle for modern setups).
  2. Missing deletedAt Field:

    • If the deletedAt field is not defined in your document, soft-delete will fail silently. Ensure your document has:
      /**
       * @MongoDB\Field(type="date")
       */
      private $deletedAt;
      
  3. Query Caching Issues:

    • Soft-deleted records are excluded by default. If you rely on query caching (e.g., @Cache), ensure your cache invalidation logic accounts for soft-deletes.
  4. Repository Method Confusion:

    • findAllWithDeleted() is not a standard Doctrine method. Use:
      $dm->getRepository('AppBundle:User')->createQueryBuilder()
          ->getQuery()
          ->execute();
      
      Or extend the repository to add custom methods.
  5. Transaction Rollbacks:

    • If a soft-delete fails mid-transaction (e.g., due to validation), the deletedAt field may be left in an inconsistent state. Always wrap in transactions:
      $dm->beginTransaction();
      try {
          $user->delete();
          $dm->flush();
          $dm->commit();
      } catch (\Exception $e) {
          $dm->rollBack();
          throw $e;
      }
      

Debugging

  1. Check for Silent Failures:

    • Verify soft-deletes by inspecting the deletedAt field directly:
      $user = $dm->find('AppBundle:User', $id);
      var_dump($user->getDeletedAt()); // Should return a DateTime or null
      
  2. Enable Doctrine Logging:

    • Add to config.yml to debug queries:
      doctrine_mongodb:
          logging: true
      
    • Check logs for unexpected query behavior (e.g., missing deletedAt filters).
  3. Field Name Mismatch:

    • If soft-deletes don’t work, confirm the deleted_field_name in config.yml matches your document’s field (e.g., deletedAt).

Extension Points

  1. Custom Soft-Delete Logic:

    • Override the delete() method in your document:
      public function delete()
      {
          $this->setDeletedAt(new \DateTime());
          // Add custom logic (e.g., log deletion)
      }
      
  2. Add Soft-Delete to Existing Documents:

    • If you can’t modify the original document, create a trait:
      trait SoftDeletable
      {
          public function delete()
          {
              $this->setDeletedAt(new \DateTime());
          }
      }
      
      Then use it in your document:
      use Doctrine\ODM\MongoDB\SoftDelete\SoftDeletable;
      
      class User {
          use SoftDeletable;
          // ...
      }
      
  3. Global Soft-Delete Filter:

    • Add a listener to globally exclude soft-deleted records (if not handled by the bundle):
      $dm->getEventManager()->addEventListener(
          'preFind',
          function ($event) {
              $query = $event->getQuery();
              $query->field('deletedAt')->equals(null);
          }
      );
      
  4. Alternative Field Names:

    • Change the deleted_field_name in config.yml to match your preference (e.g., isDeleted as a boolean):
      doctrine_mongodb_softdelete:
          deleted_field_name: isDeleted
      
      Then update your document to handle boolean logic.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope