worksome/foggy
Worksome Foggy is a Laravel package for anonymizing sensitive model data. Configure which attributes should be fogged, and Foggy replaces them with realistic fake values so you can safely use production-like data in local and staging environments.
composer require worksome/foggy --dev. It is a development/CI tool, not something that should be present in a production autoload path if you can avoid it.php artisan vendor:publish --provider="Worksome\Foggy\FoggyServiceProvider" (or --tag=foggy-config) and open config/foggy.php. This file — not the source — is where 90% of your work happens.php artisan list | grep foggy and php artisan help <command> before reading the README; the exact verb (foggy:dump, foggy:export, etc.) and flags are the fastest thing to confirm against your installed version rather than trusting a blog post.users: emails, names, phone numbers, password hashes, remember tokens). Add a rule that replaces those columns, point Foggy at a local database, and inspect the output with mysql/psql before you touch anything else.Default-deny on sensitive tables. Configure an explicit allowlist of tables to include (or a denylist of framework noise like jobs, failed_jobs, cache, sessions, telescope_*). Anything not explicitly handled should be excluded, not passed through — the failure mode of a sanitizer is silent leakage.
Column rules as the unit of work. For each included table, describe per-column behavior: drop the column, replace with a constant, replace with a generated fake value, or hash the original. Keep primary keys and foreign keys intact unless you are deliberately re-keying everything.
Keep referential integrity with deterministic hashing. If users.email is hashed, hash it with a fixed application secret so the same input always maps to the same output. Do the same for any column joined across tables. Random fakers break joins; deterministic transforms don't.
Preserve reference data verbatim. Countries, currencies, permission names, plan definitions — copy these tables untouched. Sanitizing them creates a database that looks fine but behaves differently from production, which defeats the point of staging.
Profile by environment. Keep a local profile that scrubs less (you often want your own account intact to log in and debug) and a staging/shared profile that scrubs aggressively. Drive the profile from an env var so the same command works in both places.
Custom transformers for domain types. When you have a value object, an encrypted cast, or a JSON blob with embedded PII, write a small transformer class implementing the package's contract and register it in the config. This is the intended extension point and keeps application-specific logic out of the config file.
Wire it into a dump/restore script, not into your head. Put the command behind a Composer script or a Makefile target (make dump-scrubbed), so nobody on the team ever runs a raw mysqldump "just this once." In CI, run it after your test suite against a seeded database to catch config drift when migrations add new columns.
Review the config in code review. Any migration that adds a users column should come with a diff to config/foggy.php. Add a note to your PR template; this is the only durable defense against a new PII column slipping through.
users.iban is dumped in the clear until someone remembers. Prefer table-level drop-and-rebuild semantics where possible, and add a test that asserts a known sentinel value is absent from the output.parent_id chains and commentable_type/commentable_id pairs break the moment you renumber IDs. Either keep IDs stable or don't touch IDs at all.php artisan config:cache on a machine that then runs a dump will use the cached, possibly production-profile config. Clear the cache in your dump script and assert the profile at runtime.app()->environment('production') and no explicit override flag is set, abort. A sanitizer pointed at the wrong DSN is worse than no sanitizer, because people trust it.php artisan tinker before reading package source.composer.json, read the changelog on every bump, and expect to read the source when something is off. Keep a thin wrapper (your own Artisan command or script) around Foggy's command so a breaking upstream change is a one-file fix rather than a search across the team's shell history.How can I help you explore Laravel packages today?