chamber-orchestra / doctrine-extensions-bundle
Lightweight Symfony Doctrine ORM extensions for PostgreSQL — entity traits, soft-delete filter, repository base classes, decimal type, random() DQL
Package info
github.com/chamber-orchestra/doctrine-extensions-bundle
Type:symfony-bundle
pkg:composer/chamber-orchestra/doctrine-extensions-bundle
Requires
- php: ^8.5
- doctrine/doctrine-bundle: 3.2.*
- doctrine/orm: ^3.0
- symfony/clock: 8.0.*
- symfony/config: 8.0.*
- symfony/dependency-injection: 8.0.*
- symfony/framework-bundle: 8.0.*
- symfony/runtime: 8.0.*
- symfony/uid: 8.0.*
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.75
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.0
- symfony/test-pack: ^1.2
Conflicts
This package is auto-updated.
Last update: 2026-02-22 17:40:50 UTC
README
Lightweight Symfony bundle providing reusable Doctrine ORM extensions for PostgreSQL: entity traits with matching contract interfaces, a soft-delete SQL filter, extended repository base classes, a custom decimal DBAL type, and a random() DQL function.
Requirements
- PHP ^8.5
- Symfony 8.0
- Doctrine ORM 3 / DoctrineBundle 3.2
- PostgreSQL
Installation
composer require chamber-orchestra/doctrine-extensions-bundle
If you are not using Symfony Flex:
// config/bundles.php return [ ChamberOrchestra\DoctrineExtensionsBundle\ChamberOrchestraDoctrineExtensionsBundle::class => ['all' => true], ];
Features
Entity Traits & Contract Interfaces
Each trait has a corresponding interface in Contracts\Entity. Implement the interface and use the trait:
use ChamberOrchestra\DoctrineExtensionsBundle\Contracts\Entity\IdInterface; use ChamberOrchestra\DoctrineExtensionsBundle\Contracts\Entity\SoftDeleteInterface; use ChamberOrchestra\DoctrineExtensionsBundle\Contracts\Entity\ToggleInterface; use ChamberOrchestra\DoctrineExtensionsBundle\Entity\IdTrait; use ChamberOrchestra\DoctrineExtensionsBundle\Entity\SoftDeleteTrait; use ChamberOrchestra\DoctrineExtensionsBundle\Entity\ToggleTrait; use ChamberOrchestra\DoctrineExtensionsBundle\Entity\VersionTrait; class Article implements IdInterface, SoftDeleteInterface, ToggleInterface { use IdTrait; use SoftDeleteTrait; use ToggleTrait; use VersionTrait; }
| Trait | Interface | Fields & Methods |
|---|---|---|
IdTrait |
IdInterface |
UUID primary key (caller-assigned). getId(): Uuid |
GeneratedIdTrait |
GeneratedIdInterface |
UUID primary key (auto-generated, nullable before persist). getId(): ?Uuid |
SoftDeleteTrait |
SoftDeleteInterface |
deletedDatetime column. isDeleted(), delete(), restore() |
ToggleTrait |
ToggleInterface |
enabled boolean column. isEnabled(), toggle(), enable(), disable() |
VersionTrait |
— | Doctrine @Version column using DatePoint (microsecond precision). getVersion() |
Soft-Delete Filter
Automatically appends deleted_datetime IS NULL to queries for entities implementing SoftDeleteInterface. Bypass per entity when needed:
$filter = $entityManager->getFilters()->enable('soft_delete'); $filter->disableForEntity(Article::class); // include soft-deleted articles $filter->enableForEntity(Article::class); // re-enable filtering
Repository Base Classes
Two base classes provide getOneBy() and indexBy() out of the box:
ServiceEntityRepository— extends Doctrine bundle'sServiceEntityRepository, adds$cacheableparameter tocreateQueryBuilder()EntityRepository— extends Doctrine ORM'sEntityRepository, implementsServiceEntityRepositoryInterface
use ChamberOrchestra\DoctrineExtensionsBundle\Repository\ServiceEntityRepository; class ArticleRepository extends ServiceEntityRepository { // getOneBy(criteria, orderBy) — throws EntityNotFoundException if not found // indexBy(criteria, orderBy, field) — returns array of field values matching criteria }
Custom Decimal DBAL Type
DecimalType overrides Doctrine's DecimalType to ensure convertToPHPValue() always returns ?string with scalar type validation.
DQL Random Function (PostgreSQL)
Maps random() DQL to PostgreSQL random():
# config/packages/doctrine.yaml doctrine: orm: dql: numeric_functions: random: ChamberOrchestra\DoctrineExtensionsBundle\Function\Random
$qb->select('a')->from(Article::class, 'a')->orderBy('random()');
Testing
composer test
License
MIT