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.
- PHP ^8.5
- Symfony 8.0
- Doctrine ORM 3 / DoctrineBundle 3.2
- PostgreSQL
composer require chamber-orchestra/doctrine-extensions-bundleIf you are not using Symfony Flex:
// config/bundles.php
return [
ChamberOrchestra\DoctrineExtensionsBundle\ChamberOrchestraDoctrineExtensionsBundle::class => ['all' => true],
];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() |
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 filteringTwo 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
}DecimalType overrides Doctrine's DecimalType to ensure convertToPHPValue() always returns ?string with scalar type validation.
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()');composer testMIT