Skip to content

Phauthentic/symfony-doctrine-schema-loader

Repository files navigation

Symfony Doctrine Schema Loader

Define database schemas programmatically in PHP classes and generate Doctrine Migrations from them.

This library lets you define tables, columns, indexes, and foreign keys in *Schema.php classes instead of using ORM entities or manual migration files. The schema loader discovers these classes across configured paths, merges their definitions, and provides a SchemaProvider for Doctrine Migrations—so running migrations:diff produces a migration file that brings your database in sync with your programmatic schema.

When to use this – Use this library when you work without Doctrine ORM (e.g. plain DBAL, raw SQL, or a custom data layer) and want a modular setup where each module or capability contributes its own schema definitions. The loader discovers *Schema.php files via paths or glob patterns, so modules can ship their schemas alongside their code and migrations stay in sync automatically.

Requirements

  • PHP 8.4+
  • Symfony 7.4 or 8.0 (doctrine-bridge)
  • Doctrine DBAL 4.4+
  • Doctrine Migrations 3.9+

Usage

composer require phauthentic/symfony-doctrine-schema-loader

Schema Definition Interface

Implement SchemaDefinitionInterface in classes that define database objects. Each class receives a Schema instance and adds tables, sequences, and other objects via the Doctrine DBAL Schema API.

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Types\Types;
use Phauthentic\SymfonyDoctrineSchemaLoader\Schema\SchemaDefinitionInterface;

final class UserSchema implements SchemaDefinitionInterface
{
    public function define(Schema $schema): void
    {
        $table = $schema->createTable('user');
        $table->addColumn('id', Types::INTEGER)
            ->setAutoincrement(true)
            ->setNotnull(true);
        $table->addColumn('email', Types::STRING, ['length' => 255])
            ->setNotnull(true);
        $table->setPrimaryKey(['id']);
    }
}

You can extend AbstractSchemaDefinition for a no-op base implementation.

Schema Loader

SchemaLoader implements SchemaLoaderInterface and scans directories recursively for PHP files matching *Schema.php (or a custom suffix), loads classes implementing SchemaDefinitionInterface, and merges their definitions into a single Schema. Depend on SchemaLoaderInterface when you need to inject a schema loader.

use Phauthentic\SymfonyDoctrineSchemaLoader\Loader\SchemaLoader;

$loader = new SchemaLoader([
    'src/Capability/Alpha/Infrastructure/Persistence/Doctrine/Schema',
    'src/Capability/Beta/Infrastructure/Persistence/Doctrine/Schema',
]);

$schema = $loader->load();

// With glob pattern (discovers all matching directories)
$loader = new SchemaLoader([
    'src/Capability/*/Infrastructure/Persistence/Doctrine/Schema',
]);
$schema = $loader->load();

Doctrine Migrations Integration

LoaderSchemaProvider implements Doctrine\Migrations\Provider\SchemaProvider and delegates to SchemaLoader. Wire it into Doctrine Migrations so the diff command uses your programmatic schemas instead of ORM metadata.

use Doctrine\Migrations\DependencyFactory;
use Doctrine\Migrations\Provider\SchemaProvider;
use Phauthentic\SymfonyDoctrineSchemaLoader\Loader\SchemaLoader;
use Phauthentic\SymfonyDoctrineSchemaLoader\Provider\LoaderSchemaProvider;

$loader = new SchemaLoader($paths);
$provider = new LoaderSchemaProvider($loader);

$dependencyFactory->setService(SchemaProvider::class, $provider);

Symfony Integration

When using doctrine/doctrine-migrations-bundle, register the provider as a service and inject it into the migrations dependency factory:

# config/services.yaml
services:
    Phauthentic\SymfonyDoctrineSchemaLoader\Loader\SchemaLoader:
        arguments:
            $paths:
                - '%kernel.project_dir%/src/Capability/Alpha/Infrastructure/Persistence/Doctrine/Schema'
                - '%kernel.project_dir%/src/Capability/Beta/Infrastructure/Persistence/Doctrine/Schema'

    Phauthentic\SymfonyDoctrineSchemaLoader\Provider\LoaderSchemaProvider:
        arguments:
            $loader: '@Phauthentic\SymfonyDoctrineSchemaLoader\Loader\SchemaLoader'

Then configure the bundle to use your provider (e.g. via a compiler pass or by setting SchemaProvider::class in the dependency factory before it is frozen).

Why Programmatic Schemas?

  • No ORM required – Define schemas without Doctrine ORM entities.
  • Modular – Organize schema definitions by capability or bounded context.
  • Testable – Schema classes are plain PHP; easy to unit test.
  • Explicit – Tables and columns are defined in one place, close to the code that uses them.

License

This library is under the MIT license.

About

Loads PHP classes that defines DB schemas from modules or other structures.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors