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

ibexa/doctrine-schema

Symfony bundle that abstracts cross-DBMS schema import/export. Defines a custom YAML schema format, imports YAML into Doctrine DBAL Schema, exports Schema back to YAML, and provides an event-driven SchemaBuilder extension point via subscribers.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require ibexa/doctrine-schema
    

    Ensure your project uses Symfony 7.x (or 6.x for v4.x) and PHP 8.3+ (v5.x).

  2. Enable the Bundle Add to config/bundles.php:

    Ibexa\DoctrineSchema\DoctrineSchemaBundle::class => ['all' => true],
    
  3. Define a Schema File Create a YAML file (e.g., config/schema.yml) with a custom schema format:

    tables:
      users:
        columns:
          id: { type: integer, autoincrement: true, primary: true }
          name: { type: string, notnull: true }
    
  4. First Use Case: Import Schema Inject SchemaBuilder and build the schema:

    use Ibexa\DoctrineSchema\Builder\SchemaBuilder;
    
    public function __construct(private SchemaBuilder $schemaBuilder) {}
    
    public function importSchema(): void
    {
        $schema = $this->schemaBuilder->buildSchema();
        // Use with Doctrine DBAL (e.g., $connection->getSchemaManager()->createSchema($schema))
    }
    

Implementation Patterns

Core Workflows

1. Schema Definition & Import

  • Centralized Schema Management: Store schema definitions in YAML files (e.g., config/schema/*.yml) for modularity.
  • Dynamic Loading: Use SchemaBuilderEvent to merge multiple schema files:
    // src/EventSubscriber/LoadSchemasSubscriber.php
    use Ibexa\Contracts\DoctrineSchema\Event\SchemaBuilderEvent;
    use Ibexa\Contracts\DoctrineSchema\SchemaBuilderEvents;
    
    class LoadSchemasSubscriber implements EventSubscriberInterface
    {
        public static function getSubscribedEvents(): array
        {
            return [SchemaBuilderEvents::BUILD_SCHEMA => 'onBuildSchema'];
        }
    
        public function onBuildSchema(SchemaBuilderEvent $event): void
        {
            $files = glob(__DIR__.'/../../config/schema/*.yml');
            foreach ($files as $file) {
                $event->getSchemaBuilder()->importSchemaFromFile($file);
            }
        }
    }
    

2. Schema Export

  • Export an existing Doctrine\DBAL\Schema\Schema to YAML for version control or debugging:
    use Ibexa\DoctrineSchema\Exporter\SchemaExporter;
    
    public function __construct(private SchemaExporter $exporter) {}
    
    public function exportSchema(\Doctrine\DBAL\Schema\Schema $schema): string
    {
        return $this->exporter->export($schema);
    }
    

3. Integration with Doctrine Migrations

  • Use the schema in migrations to ensure consistency:
    use Doctrine\DBAL\Schema\Schema;
    use Ibexa\DoctrineSchema\Builder\SchemaBuilder;
    
    public function up(Schema $schema): void
    {
        $customSchema = $this->schemaBuilder->buildSchema();
        $schema->mergeFrom($customSchema);
    }
    

4. Environment-Specific Schemas

  • Override schemas per environment (e.g., config/schema/dev.yml, config/schema/prod.yml) and load them conditionally:
    $event->getSchemaBuilder()->importSchemaFromFile(
        __DIR__.'/../../config/schema/'.env('APP_ENV').'.yml'
    );
    

Advanced Patterns

Event-Driven Extensions

  • Modify Schema at Runtime: Subscribe to SchemaBuilderEvents::BUILD_SCHEMA to add/alter tables/columns dynamically:
    public function onBuildSchema(SchemaBuilderEvent $event): void
    {
        $schema = $event->getSchemaBuilder()->getSchema();
        $schema->createTable('audit_log')->addColumn('action', 'string');
    }
    

Schema Validation

  • Validate YAML schemas against a schema (e.g., using Symfony’s Yaml component) before importing:
    use Symfony\Component\Yaml\Yaml;
    
    $yaml = Yaml::parseFile('config/schema.yml');
    if (!isset($yaml['tables'])) {
        throw new \RuntimeException('Invalid schema: missing "tables" key');
    }
    

Testing

  • Isolated Schema Testing: Use the exporter to compare schemas in tests:
    $this->assertEquals(
        file_get_contents('tests/_data/schema.yml'),
        $this->exporter->export($schema)
    );
    

Gotchas and Tips

Pitfalls

  1. PHP 8.3+ Requirement (v5.x)

    • Ensure your project uses PHP 8.3+. Older versions will fail with RuntimeException.
    • Fix: Downgrade to ibexa/doctrine-schema:^4.6 if needed.
  2. Symfony Version Mismatch

    • v5.x requires Symfony 7.x; v4.x supports Symfony 6.x.
    • Fix: Align versions in composer.json or use the correct branch.
  3. YAML Parsing Quirks

    • The custom YAML format is not standard Doctrine YAML. Example:
      # Valid
      columns:
        id: { type: integer, primary: true }
      
      # Invalid (will fail silently or cause errors)
      columns:
        id: integer  # Missing key structure
      
    • Tip: Validate YAML with symfony/yaml before importing.
  4. Event Priority Collisions

    • Subscribers with the same priority may override each other. Use unique priorities (e.g., 100, 200):
      SchemaBuilderEvents::BUILD_SCHEMA => ['onBuildSchema', 200]
      
  5. Doctrine DBAL Schema Merging

    • When merging schemas, order matters. Tables/columns defined later may overwrite earlier ones.
    • Tip: Use SchemaBuilderEvent to ensure dependencies are loaded first.

Debugging Tips

  1. Inspect the Schema Object

    • Dump the Doctrine\DBAL\Schema\Schema object to debug:
      $schema = $this->schemaBuilder->buildSchema();
      dump($schema->toSql($connection->getDatabasePlatform()));
      
  2. Enable Debugging for Events

    • Log event subscribers to debug priority/order:
      $dispatcher = $container->get('event_dispatcher');
      dump($dispatcher->getListeners(SchemaBuilderEvents::BUILD_SCHEMA));
      
  3. Validate YAML Syntax

    • Use symfony/yaml to validate files before importing:
      try {
          Yaml::parseFile('schema.yml');
      } catch (\Exception $e) {
          throw new \RuntimeException('Invalid YAML: '.$e->getMessage());
      }
      

Extension Points

  1. Custom Schema Types

    • Extend the schema format by creating a custom SchemaImporter:
      use Ibexa\Contracts\DoctrineSchema\SchemaImporterInterface;
      
      class CustomSchemaImporter implements SchemaImporterInterface
      {
          public function import(string $yaml): \Doctrine\DBAL\Schema\Schema
          {
              // Parse custom YAML and build schema
          }
      }
      
    • Register it as a service with the ibexa.doctrine_schema.schema_importer tag.
  2. Post-Import Hooks

    • Use SchemaBuilderEvents::POST_BUILD to run logic after schema construction:
      SchemaBuilderEvents::POST_BUILD => 'onPostBuild'
      
  3. Schema Diffing

    • Compare schemas between environments using the exporter:
      $prodSchema = $this->exporter->export($prodSchemaObj);
      $devSchema  = $this->exporter->export($devSchemaObj);
      $this->assertEquals($prodSchema, $devSchema);
      

Configuration Quirks

  1. Bundle Prefix

    • The bundle uses ibexa.doctrine_schema as the default configuration key. Override in config/packages/ibexa_doctrine_schema.yaml if needed.
  2. Autowiring

    • Ensure SchemaBuilder, SchemaImporter, and SchemaExporter are autowired. If not, add to services.yaml:
      services:
          Ibexa\DoctrineSchema\Builder\SchemaBuilder: ~
      
  3. Doctrine DBAL Dependency

    • The package requires doctrine/dbal. Install it if missing:
      composer require doctrine/dbal
      
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.
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
spatie/mailcoach-vapor