22h / doctrine-garbage-collection-bundle
A Symfony bundle for automated Doctrine entity garbage collection.
Package info
gitlab.com/22h-open/doctrine-garbage-collection-bundle
Type:symfony-bundle
pkg:composer/22h/doctrine-garbage-collection-bundle
Requires
- php: >=8.2
- doctrine/doctrine-bundle: ^2.10|^3.0
- doctrine/orm: ^2.15|^3.0
- symfony/framework-bundle: ^6.0|^7.0|^8.0
Requires (Dev)
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.0
README
A Symfony bundle for automated Doctrine entity garbage collection using PHP 8 attributes.
Features
- Automated Cleanup: Easily define cleanup rules directly in your services.
- Simple Configuration: Use attributes to specify which entities should be deleted based on date fields.
- Complex Logic: Define custom QueryBuilders for more advanced deletion logic.
- Iterative Deletion: Support for large datasets by iterating and flushing in batches (useful for triggering Lifecycle Events).
- Dry Run Support: Safely preview what would be deleted before executing.
Installation
Install the bundle via Composer:
composer require 22h/doctrine-garbage-collection-bundle
Usage
1. Tag your Service
To enable garbage collection for a specific entity, create a service and mark it with the SupportsGarbageCollection attribute.
use TwentyTwo\DoctrineGarbageCollection\Attribute\SupportsGarbageCollection;
use TwentyTwo\DoctrineGarbageCollection\Attribute\GarbageCollectionSimple;
use App\Entity\OldLog;
#[SupportsGarbageCollection(entityClass: OldLog::class)]
#[GarbageCollectionSimple(fieldName: 'createdAt', dateInterval: 'P1M')]
class LogGarbageCollector
{
}
2. Simple Garbage Collection
The GarbageCollectionSimple attribute allows you to delete entities where a specific field is older than a given DateInterval.
fieldName: The entity field to check (e.g.,createdAt).dateInterval: A PHPDateIntervalstring (e.g.,P1Mfor 1 month,P1Yfor 1 year).iteratingResult: If set totrue, entities will be loaded and removed one by one (triggering Doctrine events). Iffalse, a singleDELETEquery is executed.
3. Complex Garbage Collection
For more advanced logic, use the GarbageCollectionComplex attribute on a method that returns a Doctrine QueryBuilder.
use TwentyTwo\DoctrineGarbageCollection\Attribute\SupportsGarbageCollection;
use TwentyTwo\DoctrineGarbageCollection\Attribute\GarbageCollectionComplex;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\QueryBuilder;
use App\Entity\User;
#[SupportsGarbageCollection(entityClass: User::class)]
class UserGarbageCollector
{
#[GarbageCollectionComplex(iteratingResult: true)]
public function getUsersToDelete(EntityRepository $repository): QueryBuilder
{
return $repository->createQueryBuilder('u')
->where('u.lastLogin < :date')
->andWhere('u.isVerified = false')
->setParameter('date', new \DateTime('-1 year'));
}
}
## Events
The bundle dispatches several events during the garbage collection process, allowing you to hook into the lifecycle. All events are located in the `TwentyTwo\DoctrineGarbageCollection\Event` namespace.
- **`GarbageCollectionStartEvent`**: Dispatched before any tasks are executed.
- **`GarbageCollectionFinishEvent`**: Dispatched after all tasks have been processed.
- **`PreTaskExecutionEvent`**: Dispatched before each task. This event is stoppable; call `$event->stopPropagation()` to skip the execution of the current task.
- **`PostTaskExecutionEvent`**: Dispatched after a task has been successfully executed.
- **`GarbageCollectionErrorEvent`**: Dispatched if an error occurs during task execution.
- **`GarbageCollectionBatchEvent`**: Dispatched after each batch flush when using `iteratingResult: true`.
### Example Event Subscriber
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use TwentyTwo\DoctrineGarbageCollection\Event\PreTaskExecutionEvent; use TwentyTwo\DoctrineGarbageCollection\Event\GarbageCollectionErrorEvent;
class GarbageCollectionSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents(): array
{
return [
PreTaskExecutionEvent::class => 'onPreTaskExecution',
GarbageCollectionErrorEvent::class => 'onError',
];
}
public function onPreTaskExecution(PreTaskExecutionEvent $event): void
{
// Custom logic to skip task
// $event->stopPropagation();
}
public function onError(GarbageCollectionErrorEvent $event): void
{
$exception = $event->getException();
// Log the error or send notification
}
}
## Command Line Interface
The bundle provides a console command to execute the garbage collection.
### Dry Run (Default)
See how many entities would be deleted without actually removing them:
php bin/console twenty-two:garbage-collection
### Execute Deletion
Use the `--force` flag to actually delete the entities:
php bin/console twenty-two:garbage-collection --force
### Debugging SQL
To see the generated SQL queries:
php bin/console twenty-two:garbage-collection --dump-sql
### Filtering
You can filter by service or entity:
php bin/console twenty-two:garbage-collection --filter-entity=OldLog php bin/console twenty-two:garbage-collection --filter-service=LogGarbageCollector
## License
This bundle is released under the [MIT License](LICENSE.md).