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 Entity Generator Laravel Package

brokalia/doctrine-entity-generator

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation Add the package via Composer:

    composer require brokalia/doctrine-entity-generator
    

    Enable the bundle in config/bundles.php (Symfony only):

    return [
        // ...
        Brokalia\DoctrineEntityGeneratorBundle\BrokaliaDoctrineEntityGeneratorBundle::class => ['all' => true],
    ];
    
  2. First Command Run the generator on a domain entity:

    php artisan doctrine-generator:entity "App\\Domain\\MyDomainEntity"
    

    (Note: Laravel uses php artisan instead of bin/console.)

  3. Verify Output Check the generated Doctrine entity in:

    src/Doctrine/Entity/MyDomainEntity.php
    

First Use Case

Generate a read-only domain entity with a UUID ID and map it to a Doctrine entity for persistence:

// src/Domain/MyDomainEntity.php
class MyDomainEntity {
    public function __construct(
        private Uuid $id,
        private string $name,
    ) {}
}

Run the generator, then use the mapped entity in a repository:

// src/Repository/MyDomainEntityRepository.php
class MyDomainEntityRepository {
    public function __construct(
        private EntityManagerInterface $em,
    ) {}

    public function save(MyDomainEntity $entity): void {
        $doctrineEntity = DoctrineMyDomainEntity::fromDomain($entity);
        $this->em->persist($doctrineEntity);
        $this->em->flush();
    }
}

Implementation Patterns

Workflows

  1. Domain-First Development

    • Define domain entities without Doctrine annotations.
    • Generate Doctrine mappings on demand:
      php artisan doctrine-generator:entity "App\\Domain\\*"  # Generate all
      
  2. Value Object Handling

    • Map complex value objects to Doctrine embeddables:
      // Domain
      class Address {
          public function __construct(
              private string $street,
              private string $city,
          ) {}
      }
      
      // Generated Doctrine
      #[Embeddable]
      class DoctrineAddress {
          #[Column(type: 'string')]
          public string $street;
          // ...
      }
      
  3. Repository Integration

    • Use the generated fromDomain()/toDomain() methods:
      $domain = $repository->find($id)
          ->map(fn ($entity) => DoctrineMyDomainEntity::toDomain($entity));
      
  4. Partial Updates

    • Generate partial update DTOs for APIs:
      php artisan doctrine-generator:entity "App\\Domain\\MyDomainEntity" --partial-updates
      

Integration Tips

  • Laravel-Specific: Override the command in app/Console/Kernel.php to use php artisan:
    protected $commands = [
        \Brokalia\DoctrineEntityGeneratorBundle\Command\GenerateEntityCommand::class,
    ];
    
  • Custom Naming: Configure output paths in config/packages/brokalia_doctrine_entity_generator.yaml:
    output_dir: '%kernel.project_dir%/database/doctrine-entities'
    
  • Existing Projects: Use --force to overwrite generated files:
    php artisan doctrine-generator:entity "App\\Domain\\*" --force
    

Gotchas and Tips

Pitfalls

  1. ID Field Requirements

    • Error: Generator fails if domain entity lacks an id property.
    • Fix: Add a placeholder ID (even if unused):
      private ?string $id = null; // Temporary until domain logic is ready
      
  2. Circular References

    • Error: Generating entities with mutual references (e.g., UserPost) may cause infinite loops.
    • Fix: Use --skip-relations or manually define mappings.
  3. Type Mismatches

    • Error: Domain int mapped to Doctrine string (or vice versa) without validation.
    • Fix: Explicitly cast in toDomain()/fromDomain() methods:
      public static function toDomain(DoctrineMyDomainEntity $entity): MyDomainEntity {
          return new MyDomainEntity(
              new Uuid($entity->id), // Cast string to Uuid
              (int)$entity->quantity, // Cast int to string if needed
          );
      }
      
  4. Laravel Eloquent Conflicts

    • Error: Generated Doctrine entities may clash with Eloquent models.
    • Fix: Prefix generated classes or use separate namespaces:
      # config/packages/brokalia_doctrine_entity_generator.yaml
      namespace_prefix: 'App\\Doctrine\\'
      

Debugging

  • Dry Run: Use --dry-run to preview changes without generating files:
    php artisan doctrine-generator:entity "App\\Domain\\MyDomainEntity" --dry-run
    
  • Verbose Output: Add -v for detailed logging:
    php artisan doctrine-generator:entity "App\\Domain\\*" -v
    
  • Generated File Location: Check var/cache/dev/doctrine-generator.log for paths.

Extension Points

  1. Custom Mappers Override the default mapper by extending Brokalia\DoctrineEntityGeneratorBundle\Mapper\DefaultMapper:

    // src/Service/CustomMapper.php
    class CustomMapper extends DefaultMapper {
        protected function mapProperty(Property $property): ?Attribute {
            if ($property->getName() === 'createdAt') {
                return new Attribute([new ORM\Column(['type' => 'datetime_immutable'])]);
            }
            return parent::mapProperty($property);
        }
    }
    

    Register it in config/packages/brokalia_doctrine_entity_generator.yaml:

    mapper: App\Service\CustomMapper
    
  2. Post-Generation Hooks Use Laravel’s generated:doctrine-entity event (if supported) or add a post-command hook:

    // app/Console/Kernel.php
    protected function schedule(Schedule $schedule) {
        $schedule->command('doctrine-generator:entity {entity}')
                ->after(function () {
                    // Run migrations, tests, or other tasks
                });
    }
    
  3. Skipping Properties Exclude properties from generation with PHPDoc:

    /**
     * @DoctrineIgnore
     */
    private string $internalCache;
    

Laravel-Specific Quirks

  • Artisan vs. Console: Ensure the command is registered in app/Console/Kernel.php for Laravel.
  • Service Container: Bind the generator to the container for programmatic use:
    $this->app->bind('doctrine.entity.generator', function () {
        return new \Brokalia\DoctrineEntityGeneratorBundle\Generator();
    });
    
  • Testing: Mock the generator in tests:
    $this->app->instance('doctrine.entity.generator', $mockGenerator);
    
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.
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
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