Skip to content

Instantly share code, notes, and snippets.

Last active November 13, 2020 18:43
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asvae/f0b8b6f3eae9f72d9fa9e824c470804f to your computer and use it in GitHub Desktop.
Save asvae/f0b8b6f3eae9f72d9fa9e824c470804f to your computer and use it in GitHub Desktop.
Compare laravel and doctrine migrations

Let’s compare Laravel and Doctrine migrations

Laravel vs Doctrine

This article is targeted on Laravel beginners. No skills required whatsoever. Article is a tad opinionated, so take it with a grain of salt. Also, details are omitted for the sake of brevity.

In this article I will do the actual comparison as well as give several hints to get started.

If you’ve never heard of Doctrine, it is database abstraction layer. Sorta like Eloquent, but different type: Laravel is active record (AR), while Doctrine is object relational mapper (ORM).

Laravel migrations (docs)

In Laravel we have database/migrations folder which stores all migration classes. Laravel also keeps a table in database to keep track of past migrations. The system is dead simple and typical workflow goes as follows:

  • php artisan make:migration create_foo_column_in_bar_table --table=bar — create migration class
  • Navigate into [some numbers]_create_foo_column_in_bar_table.php file
  • Manually fill migration methods.
  • Run php artisan migrations migrate to trigger up method. Run php artisan migrations rollback to trigger down method.


  • Beginner friendly.


  • Requires a lot of code. Not noticeable when creating tables, but much more so for complex changes.
  • Migration classes have readable name, and name should be unique. So it’s reasonably possible to get a clash, if you’re not careful enough.
  • Down method is pain to write. It’s a ton of error-prone copypasta.
  • Every migration should be tested, which is very hard to do without down method.
  • All migrations must be kept forever, as they represent your schema. This brings up the humongous migrations folder after you reach several hundred migrations.

Doctrine migrations (docs)

In Doctrine we define schema as annotations on entity classes. Migrations are generated automatically by comparing your current schema to expected one. Migrations are presented in raw SQL and you can tinker them when needed (which is reasonably rare). Here’s your typical workflow:

  • Do changes in entity class.
  • Produce migration from differences: php artisan doctrine:migrations:diff.
  • Glance over migration to see if everything looks as expected.
  • Run migration: php artisan doctrine:migrations:migrate


  • Less code to type. Most noticeable when renaming columns or moving around indexes. Change one line — doctrine will do the rest.
  • Migrations are named with timestamp. Clashes are very unlikely.
  • down method is written automatically. Meaning you can also effortlessly up and down migrations. You can also move to specific migration.
  • Migrations are disposable. As they can be reliably generated from declarations. Move them, combine or delete with ease.


  • Requires a bit of studying to get a hang of.


You might want to use Doctrine migrations even without using whole Doctrine ecosystem. They're very time efficient and scalable. Laravel migrations are thus admissible only for simplest cases.

Some additional info

  • Doctrine allows to create entities with annotation from existing database. Those will likely need some fixes, but not as much as creating them from nil.
  • When using Laravel migrations, don’t employ Eloquent and use query builder only. Or even raw queries to get more on a safe side. Here's why: you might make migration, change model, make another migration. And there is a possibility that first migration is not compatible with your model anymore. This bug is prone to be found only in test or production environment and might result into partial migration, which is pain to deal with.
  • Use doctrine or Laravel migrations to perform changes on schema only (such as create tables, move columns, attach indexes etc). For data changes you can use my library. Or you can build something for yourself on top of Laravel seeders.
Copy link

The doctrine:migrations:diff doesn't exist and their documentation makes no mention of it.... ?

Copy link

asvae commented Jul 3, 2017

@BrandonLegault Sorry for late answer.

This is actually laravel doctrine command. Not doctrine itself.

Copy link

kylekatarnls commented Nov 13, 2020

All migrations must be kept forever

Not/no longer true if you mean what I think:

Migrations are disposable. As they can be reliably generated from declarations. Move them, combine or delete with ease.

No difference here with Laravel migrations, you can squash without removing to fasten the migration on new environment or squash and remove previous migrations (but in this case you need you need first to be sure every existing DBs are migrated up to the squash point, and this apply to both Laravel and Doctrine migrations).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment