Home Blog Database Migrations with Doctrine
Back to Blog
Backend

Database Migrations with Doctrine

acretph_jeffy
Jeffy D. Lepatan
General Manager
October 9, 2026
Blog Image

Doctrine Migrations provides a clear, reliable way to manage database changes across your team. By generating, executing, and tracking schema updates in source control, you avoid manual database tweaks and deployment surprises. Stick to clean practices and handle edge cases early to keep your database migrations fast, safe, and reproducible.

Introduction

Modern PHP applications depend on data models that change over time. When your database schema changes, you need a safe way to update every environment without losing data or breaking features. Doctrine Migrations gives you a straightforward workflow to version, run, and track database changes. This guide covers how it works, how to set it up, and how to use it effectively in real projects.

Why Use Doctrine Migrations

  • Consistency: Every developer runs the exact same migration scripts, keeping schemas identical across development, staging, and production environments.
  • Traceability: Each change lives in a PHP class with a unique version timestamp, so tracking down history is simple.
  • Automation: You can plug migrations right into your CI/CD pipeline to update schemas automatically on release.
  • Rollback Capability: If a deployment goes wrong, Doctrine lets you revert to a previous schema state quickly.

Setting Up Doctrine Migrations

Prerequisites

  • A Symfony or plain PHP project that already uses Doctrine ORM.
  • Composer installed on the development machine.

Installation

Run the following Composer command to add the migrations package:

```bash

composer require doctrine/migrations

```

After installation, register the migration bundle if you are using Symfony:

```yaml

config/bundles.php

Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],

```

Configuration

Create a configuration file `migrations.php` (or `doctrine_migrations.yaml` for Symfony) with the essential settings:

```php

<?php

return [

'migrations_paths' => [

'App\\Migrations' => 'src/Migrations',

],

'all_or_none' => true,

'check_database_platform' => true,

];

```

Key options:

  • migrations_paths: Maps a PHP namespace to the directory holding your migration classes.
  • all_or_none: Wraps all migration steps into one database transaction if your database engine supports it.
  • check_database_platform: Stops migrations from executing on the wrong database platform by accident.

Creating a Migration

Doctrine generates migration skeletons based on the current ORM mapping. Follow these steps:

1. Update your entity classes to reflect the desired schema change.

2. Run the diff command:

```bash

php bin/console doctrine:migrations:diff

```

Doctrine compares the current database schema with the entity metadata and creates a new migration file in the configured directory. The generated class contains two methods:

  • `up()` – Applies the schema change.
  • `down()` – Reverts the change.

Example Migration

```php

<?php

declare(strict_types=1);

namespace App\Migrations;

use Doctrine\DBAL\Schema\Schema;

use Doctrine\Migrations\AbstractMigration;

final class Version20231015094500 extends AbstractMigration

{

public function getDescription(): string

{

return 'Add email column to users table';

}

public function up(Schema $schema): void

{

$this->addSql('ALTER TABLE users ADD email VARCHAR(255) NOT NULL');

}

public function down(Schema $schema): void

{

$this->addSql('ALTER TABLE users DROP email');

}

}

```

Review the generated SQL, adjust as needed, and commit the file to version control.

Running Migrations

Executing All Pending Migrations

```bash

php bin/console doctrine:migrations:migrate

```

The command lists pending versions, asks for confirmation, and then runs each `up()` method in order.

Executing a Specific Version

```bash

php bin/console doctrine:migrations:execute --up 20231015094500

```

Use the `--down` flag to roll back a specific version.

Checking Migration Status

```bash

php bin/console doctrine:migrations:status

```

The status command reports the current version, the latest available version, and any unapplied migrations.

Managing Migration Versions

Doctrine stores migration execution history in a dedicated table (by default `doctrine_migration_versions`). This table contains a single column with the version identifiers of applied migrations.

  • Manual Insertion: You can manually insert a record if you need to mark a migration as completed without running the SQL.
  • Version Table Customization: Rename the version table using the `table_name` config key.

Best Practices

  • Keep Migrations Focused: Scope each file to a single task, like adding a column or creating an index.
  • Write Reliable Down Methods: Ensure the `down()` method cleanly undoes what `up()` changed.
  • Back Up Before Destructive Changes: Back up data or write a dedicated data preservation script before dropping tables or columns.
  • Commit Every Migration File: Treat migration code like application code and review it in pull requests.
  • Use Transactions When Available: Turn on `all_or_none` to ensure schema updates happen atomically.
  • Document Your Changes: Fill out `getDescription()` to explain why you made the change.

Common Pitfalls and How to Resolve Them

  • Missing Migration Files: If someone forgets to commit a migration, other environments fall out of sync. Use git hooks or CI checks to detect uncommitted migrations early.
  • Platform-Specific SQL: Auto-generated SQL might rely on MySQL-specific syntax. Use Doctrine's Schema abstraction methods to keep queries portable across different database engines.
  • Large Data Migrations Blocking Deployments: Heavy updates can lock tables and slow down releases. Process large datasets in smaller batches to minimize lock times.
  • Version Table Corruption: Clearing the tracking table makes Doctrine treat every migration as pending. Fix this by re-inserting missing versions or running `doctrine:migrations:sync-metadata-storage` to rebuild state.

Conclusion

Doctrine Migrations provides a clear, reliable way to manage database changes across your team. By generating, executing, and tracking schema updates in source control, you avoid manual database tweaks and deployment surprises. Stick to clean practices and handle edge cases early to keep your database migrations fast, safe, and reproducible.

Tags:
Backend
acretph_jeffy
Jeffy D. Lepatan
General Manager
Growing up in Cebu taught me the value of hard work, honesty, and earning people's trust. Those same values guide how I lead our Philippine team today. With my background in both systems administration and software development, I know exactly how much responsibility comes with building tools that businesses rely on. My goal is simple: to deliver software that works and to stand by our clients at every step. For me, success is about building long term relationships by staying transparent and always following through on our promises.

Table of Contents

AcretPhilippines Inc.
Bringing Japanese software development excellence to the Philippine market since 2019.

Acret Philippines Inc.

14th Floor Latitude Corporate Center

Cebu Business Park

Lahug, Cebu City

TEL: 032-344-3847

09:00 AM - 06:00 PM (PHT)

Head Office Acret Inc.

〒650-0011

601 Kenso Building, 2-13-3 Shimoyamate-dori

Chuo-ku Kobe-shi, Hyogo, Japan

TEL:+81 78-599-8511

10:00-17:00 JPT

© 2025 Acret Philippines Inc. All rights reserved.