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

Eventsauce Migration Generator Laravel Package

andreo/eventsauce-migration-generator

Symfony Console command that generates Doctrine Migrations for EventSauce message storage per aggregate. Configure Doctrine Migrations, then run a single command with a table prefix, selectable schemas (event/outbox/snapshot), UUID type, and optional table-name suffixes.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel

  1. Install Dependencies:

    composer require andreo/eventsauce-migration-generator doctrine/migrations symfony/console
    

    Note: Laravel 10+ supports Symfony Console via symfony/console; use laravel/symfony-cli-bridge for Artisan integration.

  2. Configure Doctrine Migrations: Add to config/packages/doctrine_migrations.yaml (Laravel’s Symfony bridge config):

    doctrine_migrations:
        storage_table_name: 'migration_versions'
        storage_table_schema: 'public'
        organizer: 'attribute'
    
  3. Register the Command: Create a custom Artisan command to wrap the Symfony command:

    php artisan make:command GenerateEventSauceMigrations
    

    Update the generated file (app/Console/Commands/GenerateEventSauceMigrations.php):

    use Andreo\EventSauce\Doctrine\Migration\Command\GenerateDoctrineMigrationForEventSauceCommand;
    use Doctrine\Migrations\DependencyFactory;
    use Symfony\Component\Console\Input\ArrayInput;
    
    class GenerateEventSauceMigrations extends Command {
        protected $signature = 'eventsauce:migrate {prefix?} {--schema= : event|outbox|snapshot|all} {--uuid-type= : binary|string}';
    
        public function handle() {
            $connection = \Doctrine\DBAL\DriverManager::getConnection(['url' => env('DATABASE_URL')]);
            $dependencyFactory = new DependencyFactory($connection);
    
            $command = new GenerateDoctrineMigrationForEventSauceCommand(
                $dependencyFactory,
                new \Andreo\EventSauce\Doctrine\Migration\Schema\TableNameSuffix('message_store')
            );
    
            $input = new ArrayInput($this->parseArgs());
            $command->run($input, new \Symfony\Component\Console\Output\BufferedOutput());
        }
    }
    
  4. First Run: Generate migrations for an aggregate with a custom prefix:

    php artisan eventsauce:migrate user_aggregate --schema=event,snapshot
    

Implementation Patterns

Workflow: Aggregate Migration Generation

  1. Define Aggregates: Ensure your EventSauce aggregates are properly configured (e.g., UserAggregate, OrderAggregate).

  2. Generate Migrations:

    # Generate all schemas (events, snapshots, outbox) for all aggregates
    php artisan eventsauce:migrate
    
    # Generate only events and snapshots for a specific prefix
    php artisan eventsauce:migrate user_ --schema=event,snapshot
    
  3. Apply Migrations: Use Laravel’s migrate command:

    php artisan migrate
    

Integration with Laravel’s EventSauce

  • Repository Configuration: Ensure your EventSauce\EventSauce repository is configured to use the generated tables:

    $repository = new EventSauce\EventSauce\Repository\Doctrine\DoctrineRepository(
        $entityManager,
        'user_aggregate_message_store', // Matches your prefix
        'user_aggregate_snapshot_store',
        'user_aggregate_outbox_store'
    );
    
  • Dynamic Table Naming: Use environment variables or config to manage prefixes/suffixes:

    // config/eventsauce.php
    'table_suffix' => env('EVENTSAUCE_TABLE_SUFFIX', 'message_store'),
    

CI/CD Automation

Add to your pipeline (e.g., GitHub Actions):

- name: Generate EventSauce Migrations
  run: php artisan eventsauce:migrate --schema=all --uuid-type=string
- name: Run Migrations
  run: php artisan migrate --env=testing

Multi-Tenant Isolation

Customize table suffixes per tenant:

# Generate for Tenant A
php artisan eventsauce:migrate tenant_a_ --schema=event

# Generate for Tenant B
php artisan eventsauce:migrate tenant_b_ --schema=event

Gotchas and Tips

Pitfalls

  1. Symfony Console Dependency:

    • Issue: Laravel doesn’t natively support Symfony Console commands.
    • Fix: Use laravel/symfony-cli-bridge or wrap the command as shown above.
    • Workaround: Manually instantiate the command in a Laravel Artisan command.
  2. UUID Type Mismatch:

    • Issue: Defaults to binary UUIDs, which may conflict with Laravel’s ramsey/uuid (string).
    • Fix: Explicitly set --uuid-type=string in CLI or configure via TableNameSuffix:
      new TableNameSuffix('message_store', 'string');
      
  3. Table Name Collisions:

    • Issue: Default suffix (message_store) may clash with existing tables.
    • Fix: Use unique prefixes (e.g., user_message_store, order_message_store).
  4. Migration Bloat:

    • Issue: One migration per aggregate can clutter your migration history.
    • Fix: Use Laravel’s --path flag to organize migrations:
      php artisan eventsauce:migrate --path=database/migrations/eventsauce
      
  5. Doctrine Migrations Configuration:

    • Issue: Misconfigured doctrine_migrations.yaml can break migration generation.
    • Fix: Verify storage_table_name and organizer settings match your setup.

Debugging Tips

  • Inspect Generated SQL: Enable Doctrine’s SQL logging to verify migrations:

    // config/database.php
    'logging' => true,
    'logging_level' => PDO::SQLITE_DEBUG,
    
  • Dry Run: Use --dry-run (if supported) or inspect generated migration files in database/migrations.

  • EventSauce Schema Validation: Cross-check generated tables against EventSauce’s schema docs.

Extension Points

  1. Custom Schema Generation: Extend the command to support non-standard EventSauce schemas:

    // Override the schema builder
    $command->setSchemaBuilder(new CustomSchemaBuilder());
    
  2. Pre/Post-Migration Hooks: Add logic before/after migration generation:

    $command->setPreGenerator(function() {
        // Add custom logic (e.g., validate aggregates)
    });
    
  3. Laravel Service Provider Integration: Register the command globally in AppServiceProvider:

    public function boot() {
        $this->commands([
            new \App\Console\Commands\GenerateEventSauceMigrations(),
        ]);
    }
    

Performance Considerations

  • Batch Processing: For large projects, generate migrations for aggregates in batches to avoid long CLI runs.
  • Parallelization: Use Laravel’s parallel:migrate (if available) or split aggregates across CI jobs.

Laravel-Specific Quirks

  1. Environment Variables: Pass dynamic config via .env:

    EVENTSAUCE_TABLE_SUFFIX=message_store
    EVENTSAUCE_UUID_TYPE=string
    

    Then access in the command:

    $suffix = new TableNameSuffix(env('EVENTSAUCE_TABLE_SUFFIX'));
    
  2. Artisan Command Caching: Clear cached commands after adding the new one:

    php artisan optimize:clear
    
  3. Testing Migrations: Use Laravel’s Schema facade to test migrations in PHPUnit:

    public function testMigrationGeneration() {
        Artisan::call('eventsauce:migrate', ['--schema' => 'event']);
        $this->assertFileExists(database_path('migrations/..._create_user_aggregate_events_table.php'));
    }
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky