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

Custom Fresh Laravel Package

ramadan/custom-fresh

A Laravel package that customizes the migrate:fresh workflow, letting you refresh your database while preserving selected tables and controlling seeding. It simplifies resetting development databases without losing essential records, making repeatable local and test setups faster and less destructiv...

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer:

composer require ramadan/custom-fresh

Laravel's package auto-discovery should register the service provider. If not, add Ramadan\CustomFresh\CustomFreshServiceProvider to config/app.php.

Where to look first:

  1. config/custom-fresh.php (publish it with php artisan vendor:publish --provider="Ramadan\CustomFresh\CustomFreshServiceProvider" if it isn't already present). This is where you list the tables to preserve.
  2. The package's service provider and console command classes under vendor/ramadan/custom-fresh/src — check exactly which command name is registered, how it hooks into migrate:fresh, and the full option signature (--drop, --drop-referenced, and any others) in src/Console.
  3. composer.json of the package to confirm the supported Laravel/PHP versions. As of v2.2.1 you want at least this version for the new validation and non-interactive behavior.

Configure and run:

// config/custom-fresh.php
return [
    'except' => [
        'countries',
        'currencies',
        'roles',
        'permissions',
        'settings',
    ],
];

Then run your refresh command as usual:

php artisan migrate:fresh

First use case: you have a large countries / currencies lookup table seeded once, and you are iterating on application migrations locally. Instead of re-seeding reference data every time, preserve those tables and let migrate:fresh rebuild only your application tables.

What changed in v2.2.1 worth knowing on day one:

  • Preserved table names are now validated. Typos and non-existent tables produce an error instead of silently doing nothing, and an empty preserved list is reported rather than treated as a normal full reset.
  • Referenced-parent warnings only appear when you pass --drop-referenced; otherwise you get informational log lines when dropped child tables reference preserved parents.
  • --drop targeting a table that shares a create migration with related tables now prompts for confirmation, and declining cancels the operation.

Implementation Patterns

Reference-data preservation for local iteration. Put slow, static lookup tables (countries, timezones, currencies) and permission tables in the except list. Your app tables drop and rebuild; the expensive seeds survive.

Environment-scoped configuration. Keep the except list in config/custom-fresh.php but drive it from env in non-production environments:

'except' => array_filter(explode(',', env('CUSTOM_FRESH_EXCEPT', ''))),

This lets CI run with an empty list (full reset) while local dev preserves data. Since v2.2.1 an empty list is explicitly validated and reported, so a misconfigured env var is loud rather than silent.

Pair with targeted seeders. After a fresh run, only seed what was dropped:

php artisan migrate:fresh && php artisan db:seed --class=DemoDataSeeder

Wrap that in a Composer script (composer fresh) so the team has one command.

Grouped-table workflows. v2.2.1 introduces awareness of tables that share a create migration. If you --drop one table from a related group, the package prompts before proceeding; declining cancels. In non-interactive mode (CI, --no-interaction) the entire related group is preserved rather than splitting the group — useful, but it means CI behavior can differ from a local run. Test both paths if your team uses grouped migrations.

Handling referenced-parent output. Dropped child tables that reference a preserved parent now emit informational log lines by default. That's the expected, benign case for lookup-data preservation — don't treat it as a failure in CI logs. Pass --drop-referenced only when you actually intend to drop referenced parents, at which point the warnings become relevant.

Testing integration. Be deliberate: if your test suite uses RefreshDatabase, the package's behavior can leak into tests depending on how the trait resets the DB. Either configure an empty except list in phpunit.xml via CUSTOM_FRESH_EXCEPT=, or use DatabaseMigrations/DatabaseTruncation explicitly. Preserving tables in tests can cause stale data between test runs.

Tenant / multi-connection setups. If you run against multiple connections, check whether the package resolves the default connection only. You may need to run the preserve-aware refresh per connection, or accept that only the default connection is handled.

CI pipelines. In CI you generally want a clean database. Set the except list to empty in CI environment config rather than relying on a locally-published config file, since the published config may not exist in the CI checkout (see Gotchas). Also decide explicitly whether CI runs interactively — the new confirmation prompts have non-interactive fallbacks that preserve whole table groups.

Schema-change workflows. When you need to alter a preserved table, temporarily remove it from the except list, run fresh, re-add it, and reseed. Document this in your team README — it's still the most common footgun.

Gotchas and Tips

Config caching. If you run php artisan config:cache (common in CI and production-like environments), edits to config/custom-fresh.php won't take effect until you re-cache. Run php artisan config:clear after changing the except list.

Published vs. package config. If the package ships a config file and you don't publish it, your edits won't exist. Conversely, after upgrading the package, your published config may be stale relative to new keys. Diff it against the vendor copy after upgrades — v2.2.x added behavior around validation and drop options, so re-read the vendor config and command signature rather than assuming v2.1 semantics.

Table name precision. Entries must match the actual table names including any prefix (DB_PREFIX) if you use one. As of v2.2.1 a non-existent name is reported as an error rather than silently ignored — good news, but it also means a stale name left in your config (e.g. a renamed table) will now fail the command instead of quietly dropping it. Prune the list when tables are renamed.

Empty preserved list. v2.2.1 validates and reports when no tables are specified. If your env-driven list is empty on purpose (CI full reset), make sure the resulting message isn't being treated as a failure by your pipeline's log parsing.

Foreign keys. Preserving a parent table while dropping child tables is fine, but migrations that add foreign keys referencing a preserved table must run after that table exists. If the preserved table is created by a migration, you now have an ordering dependency. Prefer preserving only tables that are not created by your migrations (lookup/reference data), or ensure the preserved table's migration is idempotent.

migrate:fresh flags. The package hooks a specific command path. Options like --drop-views, --drop-types, or --seed may interact differently. v2.2.1 adds --drop and --drop-referenced semantics, so read the command signature in src/Console before scripting these. If a flag isn't supported, you'll get an "option does not exist" error — a quick signal that you're hitting the package's command rather than Laravel's.

Interactive vs. non-interactive divergence. The new confirmation prompt for grouped tables behaves differently without a TTY: declining cancels, while non-interactive mode preserves the whole related group. If a CI job and a local run produce different surviving table sets, this is the first place to look.

Bypasses. Anything that calls Schema::dropAllTables() directly, or db:wipe, will ignore your except list. The package only protects the command(s) it wraps. Audit any custom reset scripts.

SQLite and in-memory databases. Preserved tables require the database to persist between runs. In-memory SQLite (:memory:) is created fresh each connection, so the feature is effectively a no-op — expected, but surprising if you're debugging tests. With v2.2.1 validation, preserved names still must exist on the connection being used.

Ordering and dependencies. Dropping tables with foreign keys can require disabling FK checks. Laravel handles this for migrate:fresh, but if your preserved tables are referenced by dropped tables, be aware of constraint errors on some drivers (notably MySQL without FOREIGN_KEY_CHECKS=0). The new informational logging is your signal that this case is being hit.

Debugging. When a table unexpectedly survives or disappears, run with -v to see the queries, confirm the resolved except list (dump it from a tinker session after booting the app), and verify config caching isn't masking your edits. Since v2.2.1, start by reading the validation error — the package now tells you when a name doesn't exist or the list is empty, which covers most misconfigurations before you get to the SQL.

Safety. This is a destructive-command customization. Never add it to production deploy scripts expecting migrate:fresh semantics to hold; guard the command behind environment checks if the package doesn't already. The new confirmation prompt is a local-nicety, not a production safety net.

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