Weave 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

Migrate Db Laravel Package

dragon-code/migrate-db

Laravel package for migrating data between different database systems. Move tables and records from MySQL, PostgreSQL, SQLite, SQL Server and more using configurable mappings, artisan commands and safe, resumable transfers.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require dragon-code/migrate-db
php artisan vendor:publish --provider="DragonCode\MigrateDb\ServiceProvider"
  1. Open config/migrate-db.php. It defines the source and target database connections (names from config/database.php, not credentials). Point them at the two connections you want to move data between — often legacy → mysql, or the same connection twice when you are only reshaping tables.
  2. Create your first transfer file in the package's migration directory (defaults to database/migrate-db/, configurable in the published config). It is a normal timestamped class extending DragonCode\MigrateDb\Migration, with up() / down() just like a Laravel migration.
  3. Run php artisan migrate:db. Use php artisan migrate:db --help on day one to see the real flags (--path, --database, rollback, etc.) your installed version exposes — the command is the authoritative reference.

Where to look first

  • The README example block — it is short and shows the base class contract ($table, up(), down()) better than the source does.
  • vendor/dragon-code/migrate-db/config/migrate-db.php — the pristine config, useful when you have already edited yours.
  • The base Migration class itself — it is thin, so reading it tells you exactly which helpers exist for copying, mapping columns, and chunking.

First real use case: a legacy application's database needs to become a fresh Laravel schema. You run php artisan migrate to build the empty target schema, then write one transfer class per table (or per logical group) and run migrate:db. This is also the pattern for a schema refactor — e.g. splitting users.name into first_name / last_name — where you cannot express the change as pure DDL.

Implementation Patterns

One migration per table, ordered by dependency. Parents before children. The package runs files in timestamp order like Laravel, so the file names are your execution plan. Do not put an entire database in one class; a failure halfway through is much easier to reason about when each unit is one table.

Raw copy vs. transformed copy. For a straight lift-and-shift, the migration body is essentially "select from source table, insert into target table" with an explicit column list (never SELECT * — column order and extras differ). For transformations, do the mapping in PHP inside up() and insert row by row or in chunks. Keep the transformation logic in a dedicated service/action class and let the migration call it — migrations are hard to unit test, services are not.

ID preservation vs. remapping. Decide this before writing anything:

  • Preserve IDs when foreign keys already reference them and you are moving an entire database. Simpler, but you must reset AUTO_INCREMENT / sequences on the target afterwards.
  • Remap IDs when merging into an existing database or de-duplicating. Build an old_id => new_id lookup map per table and rewrite dependent foreign keys through it. Do this in dependency order and persist the map (a temp table or a JSON file) so a crashed run can resume.

Chunk large tables. ->chunk(1000) / ->cursor() inside up() keeps memory flat and lets you log progress. Never get() a multi-million-row table into a collection; the package will happily try and your worker will die.

Wrap the target in a known state. In each migration: disable foreign key checks, optionally truncate the target, transfer, then re-enable. Prefer truncate over delete for reset semantics, and make the migration re-runnable on staging so you can iterate without a fresh database each time.

Separate connections per phase. If your source and target are different servers, make sure both connections are defined in config/database.php and referenced by name in config/migrate-db.php. For multi-tenant or per-environment cutovers, override the config at runtime (config(['migrate-db.source' => ...])) in a custom artisan command that wraps migrate:db — this is the main legitimate extension point.

down() is a no-op or a truncate. Data migrations are effectively irreversible. Write down() as "truncate the target table" so a rollback leaves a clean slate, and treat the real safety net as a database snapshot taken before the run.

Schedule it as a one-shot, not a sync. This is a cutover tool, not replication. If you find yourself running it nightly, you want a proper ETL or logical replication instead.

Gotchas and Tips

  • The package is archived. Pin the exact version in composer.json, and budget for forking or vendoring it if a future PHP/Laravel release breaks it. With zero dependents and no maintenance, you are the maintainer of last resort. Read the source before relying on any behaviour you cannot reproduce in a test.
  • config:cache will bite you. After changing source/target connections, run php artisan config:clear. A cached config pointing at the old connection is the single most common "it transferred nothing" cause.
  • Transactions are a trap. Large transfers blow up the rollback log, and several engines (MyISAM, some SQLite paths, and any DDL) won't roll back anyway. Chunk + idempotent-reset beats one giant transaction.
  • Foreign keys and unique indexes on the target will reject rows mid-transfer. Disable checks per migration, and transfer in dependency order — otherwise you get partial tables and a confusing constraint error pointing at the wrong migration.
  • Silent type coercion. Dates becoming 0000-00-00, booleans becoming 1/'1', JSON strings becoming escaped strings, SQLite dropping column types. Always finish a run with a validation pass: row counts per table and a checksum or spot-check of a handful of rows on both sides.
  • Charset/collation drift produces mojibake that only shows up in production. Set the connection charset explicitly and test with real accented data.
  • Reset sequences. After preserving IDs, bump AUTO_INCREMENT (MySQL) or the sequence (Postgres) past MAX(id), or the next insert collides.
  • Debug with one migration. Run --path against a single file on a copy of the data before running the full set. Add a Log::info() of "table X: read N, wrote M" at the end of each up() — a read/write mismatch is the fastest signal that filtering or a constraint silently dropped rows.
  • Back up first, always. Restore-from-snapshot is the only reliable rollback, and it should be rehearsed, not assumed.
  • Extension points are minimal by design: published config (connections + migration path), subclassing the base Migration, and wrapping the artisan command. Don't try to hook into internals; if you need more, write your own chunked transfer with Laravel's query builder and use this package only as the runner.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo