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

Database Anonymizer Laravel Package

webnet-fr/database-anonymizer

Anonymize sensitive data in Laravel databases with configurable, table-specific column replacements and Faker-powered fake values. Ideal for GDPR-friendly staging, testing, and local environments, it protects personal information while keeping your database realistic and usable.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install into the app that owns the schema, not a throwaway project.

    composer require webnet-fr/database-anonymizer --dev
    

    Because anonymization rules are tightly coupled to your migrations/models, the config should live in the same repository as the schema so it is versioned alongside it.

  2. Confirm what Composer actually resolved.

    composer show webnet-fr/database-anonymizer
    composer show doctrine/dbal
    

    v0.0.6 advertises doctrine/dbal ^3.3. Check whether that widened the constraint or replaced a ^2.x one — if it replaced it, apps pinned to dbal 2 (older Laravel) are stuck on v0.0.5 and you need to know that before you build a workflow on top of it.

  3. Publish and inspect the config first.

    php artisan vendor:publish --provider="WebnetFr\\DatabaseAnonymizer\\...ServiceProvider"
    

    The published config file is the real documentation — it defines the per-table/per-column rule structure. Read it before writing anything.

  4. Confirm the command name.

    php artisan list | grep -i anonym
    

    Don't assume a command name; the docs are sparse and the release cadence is slow (v0.0.6, a dependency-only bump, is the first release since 2022). Verify the actual signature and options before scripting it.

  5. Start with one table and one column. Pick a low-risk table (e.g. users.name, users.email) and define a single rule. Run the command against a restored, disposable copy of a dump, then query the result to confirm values changed and row counts are unchanged. This also smoke-tests that dbal 3 column introspection works against your schema.

  6. First real use case: restore a production dump into a local/staging database, run the anonymizer, then point your .env at it. This becomes the repeatable "sanitize the dump" step in your onboarding docs instead of a wiki page of hand-written UPDATE statements.

Implementation Patterns

Rules-as-config, applied per table. Define a map of table => [column => anonymizer]. Keep the config flat and explicit; avoid clever loops that generate rules, because reviewers need to see exactly which PII columns are covered.

Faker-backed anonymizers for realistic dev data. Use Faker for values your UI actually exercises — names, emails, phone numbers, addresses — so views and search behave like production. For columns your app validates (e.g. email with a unique index), use Faker's unique modifier or a deterministic pattern like user{id}@example.test.

Preserve referential integrity deliberately. Foreign keys are the main thing that breaks naive scripts. Two workable patterns:

  • Shared value per entity: derive the fake email from the primary key (user{id}@example.test) so users.id and orders.user_email stay consistent without a join.
  • Anonymize the parent, leave FK columns alone when the FK points at an already-anonymized row. Prefer this for integer FKs; the child rows reference the same untouched IDs.

Custom anonymizers for domain columns. For anything Faker can't express (national ID formats, hashed tokens, internal account numbers), implement a custom anonymizer class and register it in config. This is the intended extension point — keep custom classes in app/Support/Anonymizers and unit-test their output format, since the package can't validate your domain rules.

Pipeline integration. Wrap the artisan call in a shell script or Composer script so it's one command:

mysql < dump.sql && php artisan <anonymize-command> && php artisan migrate

Wire the same script into CI for ephemeral test databases, and gate it behind an APP_ENV !== production check in your wrapper — belt and braces alongside any package-level guard.

Environment-safety pattern. Never rely solely on the package to refuse production. Add an explicit guard in your wrapper script that aborts if DB_HOST matches the production host, and require an --force-style confirmation for anything ambiguous.

Review checklist in the PR. Treat the config file like a security artifact: when a migration adds a PII column, the same PR must add a rule. Add a test that introspects the schema for known-sensitive column names and asserts each appears in the anonymization config.

Gotchas and Tips

  • No undo. The command mutates in place. Always run against a restored copy or take a dump first. Make this automatic in your wrapper script, not a documented intention.
  • FK constraint failures. Bulk updates across parent/child tables can violate constraints mid-run. Disable FK checks for the duration inside a transaction if supported, or order operations parent-first. Test with real FK constraints enabled, not just SQLite.
  • Unique indexes. Faker's default email/name output will collide on unique columns with any real row count. Use unique generators or ID-derived values.
  • Large tables. If the package updates row-by-row via Eloquent, memory and time blow up on millions of rows. Check the implementation; prefer chunked update statements in your own custom anonymizer for large tables.
  • Config caching. After editing rules, run php artisan config:clear (or config:cache) — a stale cached config silently anonymizes the wrong columns, or none.
  • Faker seed and locale. Set a fixed seed for reproducible dumps across machines, and set the locale to match your users so phone/address formats don't break validation in dev.
  • dbal 3 changes column type reporting. If the package uses doctrine/dbal for schema introspection, dbal 2 → 3 changed the type API substantially (type objects instead of strings, dropped Type::getType usage). If you upgrade dbal alongside this release, re-verify that JSON/enum/text columns are still detected and that your rules still fire on them — a type miss can silently skip a column.
  • Dependency-only releases aren't maintenance. v0.0.6 widens dbal support and nothing else — no new anonymizers, no bug fixes, no doc changes. Treat that as "still installable" rather than "actively maintained", and pin the version so a future breaking bump doesn't surprise you. If it ever stops installing, the config format still makes a good spec for a small in-house command.
  • JSON and cast columns. Rules apply to the raw column value, not nested JSON. Anonymizing a settings JSON blob needs a custom anonymizer that decodes, redacts keys, and re-encodes.
  • Coverage gaps are silent. The package only does what you tell it. Columns you forgot — audit_logs, password_reset_tokens, soft-deleted rows, related history tables — pass through untouched. Grep your schema for email, phone, name, address, token, ip and cross-check the config.
  • Not a compliance control. Anonymized dev data is a convenience, not a GDPR/HIPAA safeguard. Keep access controls, avoid pulling dumps you don't need, and never ship the anonymizer as justification for broader prod-dump access.
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.
mydnic/volet-feature-board-filament-plugin
wmde/email-address
refinery29/test-util
dees040/laravel-api-responses
teamzac/geocoder
ideatica/config-writer
keaton-php/pipe-dream
jacksonwebservices/laravel-user-suite
maksimru/conditional-laravel-debugbar
gismatul/nova-support-chat
gismatul/laravel-support-chat
networkrailbusinesssystems/oracle-api
alphabalex/messaging-made-easy
rawphp/warp
shootkiran/merobug
narakode/fineauth
numencode/wn-syncops-plugin
ibnnajjaar/mib-global-pay
refinery29/php-cs-fixer-config
parsnick/steak