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 Adoption Laravel Package

benkle/doctrine-adoption

Adds a small Collector + Doctrine metadata listener to enhance inheritance mapping by “adopting” child entities into a parent with a named association. Register the loadClassMetadata listener manually (including for schema creation/CLI tools).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require benkle/doctrine-adoption
    

    Ensure your project uses Doctrine ORM (v2.x+).

  2. First Use Case: Define inheritance relationships between entities. For example, if ChildEntity inherits from ParentEntity but Doctrine doesn’t recognize it due to naming conventions:

    $collector = new \Benkle\DoctrineAdoption\Collector();
    $collector->addAdoptee(ParentEntity::class, ChildEntity::class, 'child');
    
  3. Integrate with Doctrine: Add the MetadataListener to your EntityManager:

    $eventManager = new \Doctrine\Common\EventManager();
    $eventManager->addEventListener(
        \Doctrine\ORM\Events::loadClassMetadata,
        new \Benkle\DoctrineAdoption\MetadataListener($collector)
    );
    $entityManager = EntityManager::create($connection, $config, $eventManager);
    
  4. Verify: Run schema validation or migrations to confirm Doctrine now recognizes the inheritance:

    php vendor/bin/doctrine orm:schema-tool:validate
    

Implementation Patterns

Workflow: Adopting Inheritance

  1. Define Adoptions: Use Collector to map parent-child relationships, specifying the discriminator column value (e.g., 'child'):

    $collector->addAdoptee(ParentEntity::class, ChildEntity::class, 'child');
    
  2. Dynamic Adoptions: For dynamic relationships (e.g., based on config), populate the Collector in a service or bootstrap file:

    $collector = new Collector();
    foreach ($config['inheritance_map'] as $parent => $children) {
        foreach ($children as $child => $discriminator) {
            $collector->addAdoptee($parent, $child, $discriminator);
        }
    }
    
  3. Integration with Symfony: If using the bundle (benkle/doctrine-adoption-bundle), configure in config/packages/doctrine.yaml:

    doctrine_adoption:
        adoptees:
            App\Entity\ParentEntity:
                App\Entity\ChildEntity: child
    
  4. Custom Discriminator Columns: Override the default discriminator column name (type) by extending MetadataListener:

    class CustomMetadataListener extends \Benkle\DoctrineAdoption\MetadataListener {
        public function __construct(Collector $collector, string $discriminatorColumn = 'inheritance_type') {
            parent::__construct($collector, $discriminatorColumn);
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Listener Not Auto-Registered:

    • The MetadataListener must be manually added to the EventManager. Forgetting this causes Doctrine to ignore inheritance mappings.
    • Fix: Wrap EntityManager creation in a service or bootstrap file to ensure consistency.
  2. Discriminator Column Conflicts:

    • If your entities already have a type column (or your custom discriminator column), the package will overwrite its mapping.
    • Fix: Use a unique column name (e.g., entity_type) or extend MetadataListener to skip existing mappings.
  3. Schema Tool Limitations:

    • The doctrine orm:schema-tool:create command may fail if the custom EntityManager isn’t used.
    • Fix: Create a custom CLI command or script to use the configured EntityManager:
      php -r "require 'vendor/autoload.php'; $em = \App\Services\DoctrineService::getAdoptionEntityManager(); $em->getConnection()->getSchemaManager()->createSchema();"
      
  4. Circular Dependencies:

    • Adopting A → B and B → A causes infinite loops.
    • Fix: Validate your Collector mappings or use a dependency graph library to detect cycles.

Debugging Tips

  1. Enable Logging: Add a logger to MetadataListener to trace adoption events:

    $listener = new MetadataListener($collector, new \Monolog\Logger('doctrine_adoption'));
    
  2. Check Metadata: Inspect generated metadata after loading:

    $metadata = $entityManager->getClassMetadata(ChildEntity::class);
    dump($metadata->inheritanceType, $metadata->discriminatorMap);
    
  3. Test with validateSchema: Use orm:schema-tool:validate to catch mapping issues early:

    php vendor/bin/doctrine orm:schema-tool:validate --em=adoption_em
    

Extension Points

  1. Custom Adoption Logic: Extend Collector to support runtime conditions:

    class ConditionalCollector extends Collector {
        public function addAdopteeIf(string $condition, string $parent, string $child, string $discriminator) {
            if ($condition) {
                $this->addAdoptee($parent, $child, $discriminator);
            }
        }
    }
    
  2. Post-Adoption Hooks: Trigger events after adoption (e.g., for caching or logging):

    $collector->addAdoptee(ParentEntity::class, ChildEntity::class, 'child');
    $collector->onAdoptionAdded(function ($parent, $child, $discriminator) {
        // Log or cache the adoption
    });
    
  3. Database-Specific Quirks: For PostgreSQL, ensure the discriminator column is VARCHAR (not TEXT) to avoid schema issues:

    # config/packages/doctrine.yaml
    doctrine:
        dbal:
            types:
                inheritance_type: string
    
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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle