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

Doctrine Soft Delete Laravel Package

chrisbaltazar/doctrine-soft-delete

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Doctrine ORM Dependency: The package is tightly coupled to Symfony’s Doctrine ORM, which is not native to Laravel. Laravel’s default ORM is Eloquent, which uses a different query builder and event system. This creates a fundamental mismatch in how soft deletes are implemented:
    • Doctrine uses SQL filters (global query modifications).
    • Eloquent uses scopes (lazy-loaded query constraints).
  • Generated Column Limitation: The package relies on MySQL GENERATED columns for auto_generated_active_flag, which is non-portable to PostgreSQL or SQLite. Laravel’s SoftDeletes uses a simple deleted_at column, avoiding this constraint.
  • Attribute System: The #[SoftDeleteUniqueIndex] attribute is Symfony-specific and may not integrate cleanly with Laravel’s annotation/attribute systems (e.g., #[Attribute] vs. Symfony’s #[Doctrine\ORM\...]). Laravel’s equivalent would likely require a custom trait or interface.
  • Zero-Config Assumption: The package assumes Symfony’s autowiring, which doesn’t exist in Laravel. Integration would require manual service registration or a custom ServiceProvider.

Integration Feasibility

  • Doctrine in Laravel: Possible but complex:
    • Requires installing DoctrineBundle (e.g., dragonmantank/cms or symfony/doctrine-bundle) alongside Laravel.
    • Would necessitate a dual-ORM strategy, where some models use Doctrine and others use Eloquent, risking inconsistent behavior.
  • Query Filtering: Doctrine’s global SQL filters would need to be emulated in Laravel:
    • Option 1: Global query listener in Laravel to inject deleted_at checks (e.g., via AppServiceProvider).
    • Option 2: Override Eloquent’s query() method or use model events (deleting, retrieved).
    • Option 3: Hybrid approach where Doctrine models use the package’s filters, and Eloquent models use Laravel’s SoftDeletes.
  • Migration Compatibility: The package’s schema comparator reduces migration noise, but Laravel’s migrations would need adjustments:
    • GENERATED columns are MySQL-specific; PostgreSQL/SQLite would require alternative logic.
    • Existing Laravel migrations would need to be updated to handle deleted_at or generated flags.
  • Unique Index Handling: The #[SoftDeleteUniqueIndex] feature would require a custom Laravel implementation:
    • Could be replicated using database-level constraints or application logic (e.g., checking deleted_at before inserts).

Technical Risk

  • Stack Fragmentation: Introducing Doctrine into a Laravel app risks fragmenting the codebase and increasing maintenance complexity.
  • Performance Overhead: Doctrine’s global SQL filters may add minor overhead compared to Eloquent’s lazy-loaded scopes. For high-traffic apps, this could be a concern.
  • Database Portability: The reliance on MySQL GENERATED columns limits flexibility. If the app uses PostgreSQL or SQLite, this feature would need to be reimplemented or skipped.
  • Integration Bugs: Bridging Doctrine and Eloquent could introduce hidden bugs, such as:
    • Missed deleted_at checks in raw SQL queries or API calls.
    • Inconsistent behavior between Doctrine and Eloquent models.
  • Testing Effort: Requires comprehensive integration tests to ensure:
    • Soft-delete logic works uniformly across both ORMs.
    • Edge cases (e.g., bulk deletes, transactions) are handled correctly.
    • No regressions in existing functionality.

Key Questions

  1. Why Doctrine? Is there a strategic reason to adopt Doctrine ORM (e.g., legacy system, Symfony microservices)? If not, Laravel’s native SoftDeletes may be sufficient.
  2. Database Strategy: Is MySQL-only acceptable, or must the solution support PostgreSQL/SQLite? If the latter, the GENERATED column feature would need to be replaced or skipped.
  3. ORM Strategy: Will the team fully migrate to Doctrine, or is this a hybrid approach? If hybrid, how will model inheritance, relationships, and queries be managed consistently?
  4. Performance Impact: Will Doctrine’s global SQL filters introduce measurable overhead compared to Eloquent’s scopes? Is this acceptable for the app’s scale?
  5. Migration Path: Can existing Laravel migrations be adapted to work with this package, or will a rewrite be required?
  6. Team Expertise: Does the team have Doctrine ORM experience? If not, the ramp-up time for custom integrations could be significant.
  7. Feature Parity: Are all features of this package critical (e.g., auto_generated_active_flag), or can they be implemented manually in Laravel?
  8. Long-Term Maintenance: Who will maintain the integration between Doctrine and Eloquent? Will this become a long-term technical debt?

Integration Approach

Stack Fit

  • Best Fit: Teams already using Symfony + Doctrine ORM (e.g., Laravel + Symfony components) or full-stack Symfony.
  • Laravel-Specific Challenges:
    • Eloquent vs. Doctrine: The package cannot replace Laravel’s SoftDeletes without significant abstraction. A TPM must decide:
      • Option A: Use the package only for Doctrine models (if any exist) and keep Eloquent models using Laravel’s SoftDeletes.
      • Option B: Fully replace Eloquent with Doctrine (high effort, not recommended unless strategic).
      • Option C: Build a Laravel wrapper around the package to unify soft-delete logic.
    • Service Container: Symfony’s autowiring won’t work in Laravel. Would require:
      • Manual service registration in config/services.php.
      • A custom ServiceProvider to bridge Doctrine and Laravel’s DI container.
  • Hybrid Stack Options:
    • Option 1: Doctrine for Read-Heavy Operations
      • Use Doctrine for reporting, CMS, or admin panels while keeping Eloquent for CRUD.
      • Implement a facade (e.g., SoftDeleteService) to abstract soft-delete logic across both ORMs.
    • Option 2: Laravel-Only Adaptation
      • Reimplement core features as Laravel packages:
        • SQL Filter → Global Query Listener: Add a listener in AppServiceProvider to inject deleted_at checks.
        • Generated Columns → Database-Specific Logic: Skip for non-MySQL or use computed columns (PostgreSQL) or application logic.
        • Unique Index Attributes → Custom Trait: Create a trait like HasSoftDeleteUniqueIndex to handle uniqueness checks.

Migration Path

  1. Assessment Phase:
    • Audit existing models using soft deletes (e.g., use SoftDeletes trait).
    • Identify Doctrine-compatible vs. Eloquent-only models.
    • Evaluate database portability (MySQL vs. PostgreSQL/SQLite).
  2. Pilot Integration:
    • Start with a non-critical module (e.g., a Symfony-powered admin panel) to test Doctrine + Laravel coexistence.
    • Use feature flags to toggle soft-delete behavior between Eloquent and Doctrine.
  3. Incremental Adoption:
    • Phase 1: Add Doctrine ORM (if not present) via dragonmantank/cms or custom setup.
      • Configure Doctrine to coexist with Eloquent (e.g., separate database connections).
    • Phase 2: Migrate Read-Heavy Models to Doctrine, keeping Eloquent for CRUD.
      • Update migrations to support both ORMs (e.g., add deleted_at columns where needed).
    • Phase 3: Unify Soft-Delete Logic
      • Build a SoftDeleteService to handle soft deletes uniformly across both ORMs.
      • Replace Doctrine’s #[SoftDeleteUniqueIndex] with a Laravel trait for Eloquent models.
    • Phase 4: Deprecate Eloquent SoftDeletes (if fully migrated to Doctrine).
  4. Fallback Plan:
    • If integration proves too complex, roll back to Laravel’s SoftDeletes and implement missing features (e.g., unique index handling) manually.

Compatibility

  • Doctrine ORM: Requires DoctrineBundle (e.g., dragonmantank/cms) and Symfony components (e.g., doctrine/orm).
  • Laravel Eloquent: Can coexist but requires custom logic to bridge soft-delete behavior.
  • Database:
    • MySQL: Full compatibility (including GENERATED columns).
    • PostgreSQL/SQLite: Limited compatibility (generated columns not supported; require alternatives).
  • Symfony Dependencies: The package requires Symfony 6.4+, which may conflict with Laravel
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity