oscarafdev/migrations-generator
Reverse-engineer an existing database into Laravel migrations. This package inspects your tables and generates migration files with columns, indexes, and foreign keys—ideal for legacy projects. Supports MySQL, PostgreSQL, SQLite, and SQL Server.
kitloong/laravel-migrations-generator is a dev-only artisan tool that reverse-engineers an existing database into real Laravel migration files. Install it as a dev dependency and start from the command help:
composer require --dev kitloong/laravel-migrations-generator
php artisan vendor:publish --provider="KitLoong\MigrationsGenerator\MigrationsGeneratorServiceProvider" --tag=config
php artisan migrate:generate --help
Where to look first:
config/migrations-generator.php — target path, default skips, template options.php artisan migrate:generate --help — the authoritative flag list for your installed version.README compatibility table — it is the source of truth for which package line pairs with which Laravel/DBAL version.Version floor: stay on ^12.0.2 for Laravel 12. This patch aligns the 12.x line with the Carbon 3 / carbonphp/carbon-doctrine-types:^3 ecosystem by requiring doctrine/dbal:^4.0, so the composer solver no longer fights between DBAL 3 and 4.
First use case — the one this release explicitly targets — is a driver change: you have a live MariaDB/MySQL schema and you want portable migration files you can run against PostgreSQL. Point the generator at the source connection, generate into a throwaway directory, review, then run the migrations against the new driver:
php artisan migrate:generate --connection=legacy_mysql --path=database/migrations/generated
Treat the output as scaffolding, not as migrations you keep forever. Review the diff, fix the types that don't translate, then either keep them one-shot or fold them into a squashed baseline.
Scope the run deliberately. Generating an entire legacy database at once is slow and produces a wall of files. Iterate:
# one table at a time while you tune type mapping
php artisan migrate:generate --connection=legacy_mysql --tables=orders,order_items
# skip the noise
php artisan migrate:generate --ignore=jobs,failed_jobs,sessions,cache
Driver-portability workflow (the 12.0.2 use case).
database/migrations/generated/.enum(, tinyint(1), unsignedBigInteger, json, geometry, timestamp(...) precision.php artisan migrate --database=pgsql against a scratch database.pg_dump --schema-only against expectations; only then commit.Two flags materially reduce cross-driver friction:
--default-index-names and --default-fk-names — generate Laravel's deterministic identifier names instead of the source DB's, avoiding duplicate or over-length constraint names on PostgreSQL (63-char limit).--use-db-collation — only when you actually want the source collation baked in; usually you don't when changing drivers.Squashed baseline for CI. Use --squash to emit a single schema migration. This is the pragmatic pattern for test pipelines: generate once from a schema-only dump, commit the single file, and let CI migrate:fresh against it instead of replaying years of history.
Regenerating as the source schema drifts. Because each run stamps a new timestamp, generated files accumulate. Keep them in a dedicated directory (--path), never mixed into database/migrations, and delete-and-regenerate rather than layering. If the output is going to be committed, review it like any other code — an unreviewed create for a table that already exists will blow up on deploy.
Long-running / debugging runs. For wide schemas, run per-table in a loop and pass --log to capture what the generator did; it is the fastest way to see which columns it couldn't map. Bump PHP memory for large databases — introspection of hundreds of tables in one process is memory-hungry.
Extension points. Publish the config and look for the template-path and custom-type-mapping keys before forking the package. Mapping a proprietary column type is normally a config entry, not a code change. If you truly need logic, the schema-manager abstraction is where the package touches DBAL — note that 12.0.2 selects createSchemaManager() (DBAL 4) with a getSchemaManager() fallback, so any local patch you carry from the DBAL 3 era must be rebased.
--dev only. It introspects live schemas and has no business in a deploy artifact.doctrine/dbal:^3, composer will refuse. Diagnose with composer why doctrine/dbal / composer why-not doctrine/dbal ^4.0 before assuming the package is broken.carbonphp/carbon-doctrine-types:^3 → DBAL 4. If you pinned DBAL 3 "to make the generator work," you were fighting the framework; 12.0.2 removes that need. After upgrading, run composer update doctrine/dbal --with-dependencies and re-run your regression check.11.x line? Don't jump package majors casually alongside DBAL majors. Upgrade the package line that matches your Laravel version, then verify the schema manager path is exercised — 12.0.2 added a focused regression test for exactly this selection, so a green test suite on the patch is meaningful signal.down() methods are often incomplete. They typically drop the table; that's fine for scaffolding but wrong if you adopt the files as permanent migrations and later need a real rollback.tinyint(1) → boolean heuristics, enum → varchar, unsigned integers → check constraints, json vs jsonb. Always inspect the generated files rather than trusting the run's exit code.Net assessment: 12.0.2 is a small but load-bearing patch. It is not a feature release — it's a dependency-reality fix that makes the 12.x line actually installable on Laravel 12, plus a defensive compatibility shim for the DBAL schema-manager API and a regression test to keep it from breaking again. Anyone on Laravel 12 should be on this version; anyone on Laravel 11 should stay on the 11.x line and ignore it.
How can I help you explore Laravel packages today?