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

Refresher Laravel Package

amjadiqbal/refresher

A Laravel package by Amjad Iqbal that provides a simple refresher utility for resetting and restoring application data, helping developers quickly return development or testing environments to a clean, known state with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Refresher swaps Laravel's per-test migrate:fresh for a cached database snapshot, so a test suite that used to spend its first several seconds (or minutes) migrating gets a ready-to-use schema instead.

  1. Install it as a dev dependency: composer require --dev <vendor>/refresher. It requires PHP ^8.3 and symfony/process ^7.2|^8.0 after v1.1.0 — check this before upgrading on an older app.
  2. Publish the config (php artisan vendor:publish) and skim it once; the settings you'll actually touch are the snapshot path, seed_paths, and per-connection options.
  3. Build the first snapshot: php artisan refresher:snapshot. This runs a fresh migration (plus seeding, if configured) and stores the result under the configured snapshot path.
  4. In tests/TestCase.php, replace use RefreshDatabase; with use RefreshesWithRefresher; — or LazilyRefreshDatabase with LazilyRefreshesWithRefresher if that's what you use today. No other test changes are required.

First use case: a feature/integration suite with dozens of migrations where php artisan test feels slow. Run the suite before and after the trait swap and compare wall time; that delta is the whole pitch.

Verify the install with php artisan about — v1.1.0 adds a Refresher section showing the version and the resolved snapshot path, which is the fastest way to confirm the package is picking up the config you think it is.

Implementation Patterns

Keep the trait swap at the base TestCase only. Both traits are designed as drop-ins for core's equivalents; subclasses should keep using RefreshDatabase-style idioms ($seed, $seeder, #[Seed], #[Seeder], $dropViews, $dropTypes, migrateFreshUsing()) and let the trait forward them. Don't mix RefreshDatabase and RefreshesWithRefresher in the same class hierarchy.

Seeding. As of v1.1.0 the trait overrides only migrateDatabases() and passes migrateFreshUsing() through, so protected $seed = true;, protected $seeder = ...;, and the Laravel 13 #[Seed] / #[Seeder] attributes behave identically to RefreshDatabase. If you want the seeded state snapshotted instead of re-seeded per test, list your seeder/factory paths in seed_paths so the snapshot key includes them.

CI. Snapshot keys are machine-independent, so build the snapshot once in a setup job, cache the snapshot directory with your normal CI cache action, and let test jobs restore it. Use refresher:clear when you need to invalidate everything (e.g. a cache-busting key change or a corrupted artifact). Keying accounts for migration paths from loadMigrationsFrom() (discovered automatically), seeders/factories when seeding, the driver, and the migrate:fresh options — so a cache built on MySQL won't be handed to a SQLite job by accident.

Parallel testing. Each worker still needs its own database, but the snapshot makes worker startup cheap. Use --fresh-options on refresher:snapshot (or the equivalent config) when you need --drop-views / --drop-types baked into the snapshot definition, so the snapshot matches what migrate:fresh would have produced.

Per-connection setup. MySQL, MariaDB (driver => mariadb), and SQLite are handled; configure the snapshot per connection so a mysql local run and a sqlite CI run each get a sane artifact.

Local dev loop. Add a composer script ("db:snapshot": "artisan refresher:snapshot") and re-run it after pulling migrations. For a single test class, the per-test restore is fast enough that you generally don't need to reach for --filter tricks anymore.

Gotchas and Tips

  • Tables created outside migrations get dropped on MySQL restore. v1.1.0 made the restore mirror migrate:fresh (drop every table and view first). That's the right behaviour, but it means tests that lazily create tables, or a leftover table from another branch, won't survive. Never point this at a database you care about — it's migrate:fresh semantics.
  • Regenerate the snapshot when snapshot-affecting inputs change. The key covers migration paths, seeders/factories, driver, and fresh options — not your application code. If you edit a migration in place or change a seeder's contents without touching paths, rebuild explicitly with refresher:snapshot.
  • Don't override migrateDatabases() yourself. The v1.1.0 fix works precisely because the trait leaves core's bookkeeping (in-memory PDO cache, $migrated) alone and only intercepts the migration call. Custom overrides there are the most likely way to reintroduce the "unseeded database" bug from v1.0.x.
  • Upgrade check: v1.1.0 narrows symfony/process to ^7.2|^8.0 and PHP to ^8.3. Apps on Symfony 6 (older Laravel) will silently resolve to an older Refresher — pin deliberately if you're mid-upgrade.
  • MySQL credentials: passwords now flow through MYSQL_PWD rather than --password=, so no CLI warning and nothing in the process list. unix_socket connections work; long dumps no longer trip Symfony Process's 60s timeout. If you had a workaround for either, drop it.
  • SQLite WAL: the WAL is checkpointed before snapshotting and stale -wal/-shm files are removed on restore. If you see "database disk image is malformed" style errors, delete the snapshot and rebuild rather than debugging the WAL by hand.
  • Debugging: php artisan about gives version + snapshot path; refresher:clear gives you a clean slate. Those two commands cover most "why is my schema stale" reports.
  • Gitignore the snapshot directory. It's a build artifact — cache it in CI, never commit it.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource