dragon-code/laravel-data-dumper
A Laravel package that makes debugging data easier with convenient dumping helpers for inspecting variables and application state. Get clearer, more readable output while developing so you can trace values and diagnose issues faster, with a lightweight integration that fits naturally into Laravel wo...
laravel-data-dumper is a small dev-tool package that plugs into Laravel's built-in php artisan schema:dump command. Out of the box, schema:dump writes a .sql file containing only the structure of your database, which Laravel then replays on a fresh migrate/migrate:fresh to skip hundreds of migration files. The catch is that any reference data your app can't boot without (countries, currencies, roles, plans, settings, statuses) is lost. This package lets you declare those tables so their rows are exported alongside the schema and re-imported later.
Minimal setup:
# Dev dependency — you only need it locally / in CI, not in production
composer require dragon-code/laravel-data-dumper --dev
# Publish the config (tag name may vary by version; fall back to --provider)
php artisan vendor:publish --tag=data-dumper-config
# or: php artisan vendor:publish --provider="DragonCode\DataDumper\ServiceProvider"
Then edit config/data-dumper.php and list the tables whose data must survive:
return [
'tables' => [
'countries',
'currencies',
'roles',
'permissions',
'settings',
],
];
Regenerate the dump:
php artisan schema:dump
Where to look first:
config/data-dumper.php — the only knob most projects touch.database/schema/mysql-schema.sql — inspect it after dumping; you should see the usual CREATE TABLEs plus INSERT INTO ... statements for your configured tables. grep -c 'INSERT INTO' database/schema/*.sql is the quickest sanity check.--prune/--database interactions in the version you installed — this is a 35-star package, so pin it and read the changelog before upgrading.First real use case: a project with 200+ migrations and a countries table of ~250 rows plus a roles/permissions matrix. Dump once, commit the .sql, and every new teammate and every CI job gets a working database in seconds instead of minutes — with the reference data already present, so your RoleSeeder no longer has to fight the schema load.
The "reference data, not user data" rule. The whole value proposition hinges on dumping immutable, application-critical lookup tables. The pattern that works:
updateOrInsert on a natural key).Schema → data → migrations ordering. The canonical workflow on a mature project:
php artisan migrate # bring the local DB fully up to date
php artisan db:seed --class=ReferenceDataSeeder # refresh lookup rows
php artisan schema:dump # captures BOTH schema and configured data
git add database/schema/ && git commit -m "chore: refresh schema dump"
The order matters — dump after migrations and after the reference data is in its final state, otherwise you commit stale rows.
First migrate on an empty database. Laravel's MigrateCommand::prepareDatabase() loads the schema file when the migrations table doesn't yet exist. So on a fresh machine:
git clone ...
composer install
cp .env.example .env && php artisan key:generate
php artisan migrate # ← loads database/schema/mysql-schema.sql (with your INSERTs), then runs only new migrations
migrate:fresh and migrate:refresh also funnel through migrate, so the dump is used there too. migrate:rollback and db:wipe do not replay it.
CI and test-database patterns. Because the dump is just a .sql file, it's the cheapest way to stand up a test DB. In phpunit.xml or a base TestCase:
protected function setUp(): void
{
parent::setUp();
// Once per suite, not per test:
// Artisan::call('migrate:fresh');
// Then wrap each test in a transaction so the reference data persists.
}
The reference rows are constant, so they survive transaction rollbacks and you never re-seed per test. That alone can shave minutes off a large suite.
Multiple connections / databases. schema:dump is per-connection (php artisan schema:dump --database=pgsql), so if you run a separate reporting or tenant DB, dump each one and keep the data-dumper config aware of which tables belong to which connection. Keep tenant-specific dumps out of the shared config.
Pairing with seeders instead of duplicating them. Prefer making the seeder the source of truth and the dump a snapshot of it. A common split:
// ReferenceDataSeeder — idempotent, safe to re-run anywhere
foreach (config('app.countries') as $c) {
DB::table('countries')->updateOrInsert(['iso' => $c['iso']], $c);
}
Run it locally before dumping; in production you run the seeder (never the schema dump). This keeps prod and dev consistent.
Integration with spatie/laravel-permission. Roles and permissions are the classic case: you want the permission definitions in the dump but not the model_has_roles pivot (that's user data). Dump roles and permissions only, and keep role_has_permissions out — or include it if your role→permission matrix is genuinely static and you never edit it at runtime.
The dump is a frozen snapshot, not a live source. Every time you change reference data locally (new country, new plan tier), you must re-run schema:dump and commit the file — otherwise teammates keep getting the old rows and the diff between environments silently drifts. Put a reminder in your PR template.
--prune is destructive to migration files, not to the database. php artisan schema:dump --prune deletes all files in database/migrations/. If you run it by accident on a branch mid-work you'll lose uncommitted migration files. Always commit (or stash) before pruning, and never run --prune until the dump has been verified. Verify first with a plain schema:dump, inspect the .sql, then prune.
Never dump user-facing tables. This is the biggest footgun. Adding users, orders, or sessions to the config means real email addresses, password hashes, and API tokens end up in a git-tracked .sql file. Even with hashed passwords, treat it as a data leak. The config is a whitelist for a reason — keep it to reference data only.
Foreign-key insert order. mysqldump-style output generally orders tables alphabetically, so a child table (cities referencing countries) may be inserted before its parent, and migrate will fail with a FK constraint error. If you hit this, either disable FK checks in the dump, split the parent tables into an earlier connection dump, or keep dependent tables out and seed them.
Auto-increment values and hard-coded IDs. Dumps carry the AUTO_INCREMENT counter. If your seeders or config hard-code IDs, a later INSERT on a fresh DB can collide. Prefer natural keys (iso_code, slug, name) in seeders so the dumped rows and the seeded rows converge.
Database-specific output. MySQL, PostgreSQL, and SQLite dumps are not interchangeable, and the filename (database/schema/mysql-schema.sql) is connection-aware. If your team mixes MySQL locally with PostgreSQL in CI, you'll need separate dumps and a conditional --schema-path. Check config/database.php → connections.*.dump too; Laravel passes extra mysqldump flags through there, and they can interact with what this package appends.
Data can be large — watch the diff. A countries table is fine; a cities table of 140k rows will bloat every PR diff and slow CI. If the file exceeds a few MB, keep only genuinely small tables in the dump and load the rest via an external seeder or a downloaded fixture.
Debugging: inspect the artifact, not the command. If data isn't being restored, run grep -n 'INSERT INTO' database/schema/*.sql. Three outcomes tell you everything: no INSERTs → config not loading (cached config? run php artisan config:clear); INSERTs but missing rows → wrong table name in config; restore fails → FK order or a CREATE TABLE IF NOT EXISTS conflict because Laravel loaded the schema and a migration tried to re-create a table.
Config caching bites dev tools too. If config/data-dumper.php changes seem to have no effect, php artisan config:cache may be active in your environment. Run config:clear before re-dumping.
Extension points. Beyond the config, the practical extension hooks are: (1) a custom ReferenceDataSeeder invoked before dumping, (2) Laravel's connections.*.dump options for including/excluding tables at the mysqldump level, and (3) wrapping the whole thing in a Composer script ("db:refresh": ["@php artisan migrate", "@php artisan db:seed --class=ReferenceDataSeeder", "@php artisan schema:dump"]) so nobody forgets the order.
Version pinning. With 35 stars and a recent release cadence, treat the package as low-bus-factor: pin an exact version in composer.json ("dragon-code/laravel-data-dumper": "x.y.z"), keep the config file in your repo, and be ready to replace it with a 30-line custom command (run mysqldump --no-create-info for the configured tables and append the output to the schema file) if maintenance stalls. That fallback is genuinely small, which makes the dependency low-risk.
How can I help you explore Laravel packages today?