PHPackages                             chamber-orchestra/metadata-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. chamber-orchestra/metadata-bundle

ActiveSymfony-bundle[Database &amp; ORM](/categories/database)

chamber-orchestra/metadata-bundle
=================================

Symfony bundle for extending Doctrine ORM entities with custom attribute-driven metadata — cacheable mapping, embedded entity support, and autoconfigured drivers

v8.0.12(2mo ago)0627↓37.5%5MITPHPPHP ^8.5CI passing

Since Jan 4Pushed 2mo agoCompare

[ Source](https://github.com/chamber-orchestra/metadata-bundle)[ Packagist](https://packagist.org/packages/chamber-orchestra/metadata-bundle)[ Docs](https://github.com/chamber-orchestra/metadata-bundle)[ RSS](/packages/chamber-orchestra-metadata-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (11)Versions (19)Used By (5)

[![PHP Composer](https://github.com/chamber-orchestra/metadata-bundle/actions/workflows/php.yml/badge.svg)](https://github.com/chamber-orchestra/metadata-bundle/actions/workflows/php.yml)[![PHP CS Fixer](https://camo.githubusercontent.com/38a469223430dcb2e92f6ade8149f377db8bda7d1b2c6fd04015fe6659faded0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f504850253230435325323046697865722d656e61626c65642d627269676874677265656e2e737667)](https://github.com/PHP-CS-Fixer/PHP-CS-Fixer)[![Code Style: PER-CS](https://camo.githubusercontent.com/6ec1ce8cd297f8e9173b85f5c9b1831612578ea0e7fc8a55f3d33e1bdc049b57/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d5045522d2d43532d626c75652e737667)](https://www.php-fig.org/per/coding-style/)[![Code Style: Symfony](https://camo.githubusercontent.com/4bdfc5c7cdcfe89ff8a5d1f818ff1c6b6e026546c788f6f88cf2dc28710985a5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d53796d666f6e792d626c61636b2e737667)](https://symfony.com/doc/current/contributing/code/standards.html)[![PHPStan Level max](https://camo.githubusercontent.com/b6d441ad4fe8332cb16c72aa27f22cc685181dfd74ae34964afc92c6c1146b3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c2532306d61782d627269676874677265656e2e737667)](https://phpstan.org/)[![PHP 8.5](https://camo.githubusercontent.com/40afc499167234cbc9f48deebb4fac0b833dde32beb716e6737a26b359a4c0f9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e352d3737374242342e737667)](https://www.php.net/)[![Symfony 8.0](https://camo.githubusercontent.com/daaa476b3cc456701380f7d0fbdc3bbe9983e89d3267f99870daa88aa719e181/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53796d666f6e792d382e302d3030303030302e737667)](https://symfony.com/)[![Doctrine ORM 3](https://camo.githubusercontent.com/8c8b68c0a485baa4cd25005aa8e9bbe59ce922f1fe73068ee09a48302ada46f5/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f637472696e652532304f524d2d332d6f72616e67652e737667)](https://www.doctrine-project.org/)[![Latest Stable Version](https://camo.githubusercontent.com/c6552fa364f093e1703fc65479d5fb436d9f52981efed7006a9c74f2d6f042ba/68747470733a2f2f706f7365722e707567782e6f72672f6368616d6265722d6f72636865737472612f6d657461646174612d62756e646c652f76)](https://packagist.org/packages/chamber-orchestra/metadata-bundle)[![License](https://camo.githubusercontent.com/b0758060f6b8d7665f437c5bb640e486f5989ba034c68e1f16412b88ffffaf9a/68747470733a2f2f706f7365722e707567782e6f72672f6368616d6265722d6f72636865737472612f6d657461646174612d62756e646c652f6c6963656e7365)](https://packagist.org/packages/chamber-orchestra/metadata-bundle)

ChamberOrchestra Metadata Bundle
================================

[](#chamberorchestra-metadata-bundle)

A Symfony bundle for extending Doctrine ORM entities with custom attribute-driven metadata. Define PHP attributes on your entities and let autoconfigured mapping drivers turn them into cacheable, serializable metadata — with full support for embedded classes and multiple entity managers.

Features
--------

[](#features)

- **PHP attribute-based mapping** — define custom metadata using native PHP 8 attributes on entity classes and properties
- **Cacheable metadata** — multi-level cache (PSR-6 + in-memory) with serialization support for production performance
- **Embedded entity support** — automatic recursive metadata resolution for Doctrine embeddables with lazy field initialization
- **Autoconfigured mapping drivers** — implement `MappingDriverInterface` and drivers are auto-tagged via Symfony DI
- **Doctrine event integration** — hooks into `loadClassMetadata` to load extension metadata alongside Doctrine's own metadata
- **Multiple EntityManager support** — cache isolation per EntityManager via `spl_object_id` scoping
- **Zero configuration** — install the bundle and start writing drivers; no YAML/XML configuration required

Installation
------------

[](#installation)

```
composer require chamber-orchestra/metadata-bundle
```

Quick Start
-----------

[](#quick-start)

### 1. Define a Mapping Driver

[](#1-define-a-mapping-driver)

Create a mapping driver by extending `AbstractMappingDriver`. Override `getClassAttribute()` or `getPropertyAttribute()` to declare which PHP attributes your extension requires:

```
use ChamberOrchestra\MetadataBundle\Mapping\Driver\AbstractMappingDriver;
use ChamberOrchestra\MetadataBundle\Mapping\ExtensionMetadataInterface;

class TimestampableDriver extends AbstractMappingDriver
{
    protected function getClassAttribute(): string|null
    {
        return Timestampable::class;
    }

    public function loadMetadataForClass(ExtensionMetadataInterface $extensionMetadata): void
    {
        // Read attributes and populate your metadata configuration
    }
}
```

Drivers implementing `MappingDriverInterface` are automatically tagged and registered by the bundle.

### 2. Create a Metadata Factory

[](#2-create-a-metadata-factory)

Extend `AbstractExtensionMetadataFactory` to define how your extension metadata is created and loaded:

```
use ChamberOrchestra\MetadataBundle\Mapping\AbstractExtensionMetadataFactory;
use ChamberOrchestra\MetadataBundle\Mapping\ExtensionMetadataInterface;
use Doctrine\Persistence\Mapping\ClassMetadata;

class TimestampableMetadataFactory extends AbstractExtensionMetadataFactory
{
    protected function newClassMetadataInstance(ClassMetadata $metadata): ExtensionMetadataInterface
    {
        return new ExtensionMetadata($metadata);
    }

    protected function doLoadMetadata(ExtensionMetadataInterface $class): void
    {
        // Delegate to your mapping drivers
    }
}
```

### 3. React to Doctrine Events

[](#3-react-to-doctrine-events)

Use `AbstractDoctrineListener` to access extension metadata during Doctrine lifecycle events:

```
use ChamberOrchestra\MetadataBundle\EventSubscriber\AbstractDoctrineListener;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PrePersistEventArgs;
use Doctrine\ORM\Events;

#[AsDoctrineListener(event: Events::prePersist)]
class TimestampableListener extends AbstractDoctrineListener
{
    public function prePersist(PrePersistEventArgs $args): void
    {
        foreach ($this->getScheduledEntityInsertions($args->getEntityManager(), TimestampableConfiguration::class) as $metadataArgs) {
            $metadataArgs->extensionMetadata->setFieldValue(
                $metadataArgs->entity,
                'createdAt',
                new \DateTimeImmutable()
            );
        }
    }
}
```

Architecture
------------

[](#architecture)

```
MetadataSubscriber (Doctrine loadClassMetadata event)
  └── MetadataReader
        └── AbstractExtensionMetadataFactory
              ├── MappingDriverInterface[] (attribute-based mapping drivers)
              ├── ExtensionMetadataInterface (per-entity extension metadata)
              │     ├── MetadataConfigurationInterface[] (per-driver configurations)
              │     └── Embedded metadata (recursive for embeddables)
              └── PSR-6 Cache (serialized metadata storage)

```

### Key Abstractions

[](#key-abstractions)

Class / InterfaceRole`MappingDriverInterface`Extension point — implement to define attribute-driven metadata`AbstractMappingDriver`Base driver with `AttributeReader` and `supports()` logic`MetadataConfigurationInterface`Stores field mappings; serializable for Doctrine cache`AbstractDoctrineListener`Base for Doctrine listeners that need extension metadata`MetadataArgs`DTO bundling EntityManager, metadata, configuration, and entityRequirements
------------

[](#requirements)

- PHP 8.5+
- Symfony 8.0
- Doctrine ORM 3.6+
- Doctrine Bundle 3.2+

Development
-----------

[](#development)

```
composer install   # Install dependencies
composer test      # Run the test suite
```

License
-------

[](#license)

MIT

###  Health Score

49

—

FairBetter than 94% of packages

Maintenance92

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 87.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

13

Last Release

71d ago

PHP version history (2 changes)v8.0.1PHP ^8.4

v8.0.4PHP ^8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/44037eb1c8dc2c4fa9871ac213653f33e22a9348dcec7132df07cc71933f2a2e?d=identicon)[wtorsi](/maintainers/wtorsi)

---

Top Contributors

[![wtorsi](https://avatars.githubusercontent.com/u/2115840?v=4)](https://github.com/wtorsi "wtorsi (14 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (2 commits)")

---

Tags

doctrinedoctrine-extensionsdoctrine-ormembeddableentitymappingmetadataormphpphp-attributessymfonysymfony-bundlesymfonyormdoctrinemetadataentitymappingextensionSymfony Bundledoctrine-ormphp-attributesdoctrine-extensionsembeddable

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/chamber-orchestra-metadata-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/chamber-orchestra-metadata-bundle/health.svg)](https://phpackages.com/packages/chamber-orchestra-metadata-bundle)
```

###  Alternatives

[fresh/doctrine-enum-bundle

Provides support of ENUM type for Doctrine2 in Symfony applications.

4636.8M12](/packages/fresh-doctrine-enum-bundle)[sonata-project/doctrine-orm-admin-bundle

Integrate Doctrine ORM into the SonataAdminBundle

46117.7M155](/packages/sonata-project-doctrine-orm-admin-bundle)[ahmed-bhs/doctrine-doctor

Runtime analysis tool for Doctrine ORM integrated into Symfony Web Profiler. Unlike static linters, it analyzes actual query execution at runtime to detect performance bottlenecks, security vulnerabilities, and best practice violations during development with real execution context and data.

813.1k](/packages/ahmed-bhs-doctrine-doctor)[onurb/doctrine-yuml-bundle

Symfony Bundle to visualize the mapping of your entities with Yuml

4198.6k](/packages/onurb-doctrine-yuml-bundle)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1714.8k8](/packages/2lenet-crudit-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
