orange-rt/anonymize-bundle
A Symfony bundle for anonymizing Doctrine entity data, helping teams meet GDPR and privacy requirements. Configure field-level anonymization strategies to consistently scrub personal data across your application.
This is a Symfony bundle, not a Laravel package. If you're working in a Laravel codebase you cannot composer require it and expect it to work out of the box — you'd either need to adapt it or (more realistically) use fakerphp/faker directly in your own anonymization command. The guidance below assumes a Symfony app; the Laravel notes are called out separately.
Minimal steps:
composer require orange-rt/anonymize-bundle
Register the bundle (Symfony 3/4 style AppKernel, or config/bundles.php for Flex-era apps):
// config/bundles.php
return [
// ...
OrangeRT\AnonymizeBundle\AnonymizeBundle::class => ['dev' => true, 'staging' => true],
];
Then read the README config block first — the bundle is config-driven and the whole value proposition is the mapping between entity fields and Faker formatters. Look for the bundle's config key (typically under anonymize: in config/config.yml) and the console command it registers (likely something like anonymize:run or app:anonymize). Run bin/console list and grep for anonym to find the exact command name in your version — this varies across releases.
First use case: take a production dump, restore it into a staging database, then run the anonymize command to overwrite PII columns (names, emails, phones, addresses, free-text notes) before anyone touches it. This is the intended workflow and the one worth validating first.
Config-driven field mapping. The core pattern is declaring, per entity/table, which fields get replaced and with which Faker formatter. It ends up looking roughly like:
anonymize:
entities:
App\Entity\Customer:
firstName: { formatter: firstName }
lastName: { formatter: lastName }
email: { formatter: safeEmail }
phone: { formatter: phoneNumber }
notes: { formatter: realText, arguments: [200] }
Treat this as illustrative and reconcile the exact keys with the README for your pinned version.
Run it as a post-restore step, not a post-migration step. The cleanest integration is a small shell script or CI job: mysql < dump.sql && bin/console anonymize:run --env=staging. This keeps anonymization idempotent with respect to your data pipeline and avoids surprises from migrations re-inserting real seed data.
Environment-scoped registration. Register the bundle only in dev and staging in bundles.php (as shown above). Never let it be loadable in prod — one stray command invocation against a live database is irreversible.
Pair with Doctrine fixtures for a repeatable dataset. A common workflow is: anonymize an existing dump for debugging real-world data shapes, and separately maintain a Faker-based fixture set for fresh databases. The bundle handles the former; don't try to make it do both.
Custom anonymizers. If a field needs domain logic (e.g. scramble an account number while preserving a checksum), write a service implementing whatever the bundle's anonymizer interface is and reference it in config. This is the main extension point and is worth discovering early if you have non-trivial fields.
Laravel alternative. In a Laravel app, the equivalent is a custom artisan command that walks models and overwrites columns with Faker values inside a transaction:
Customer::chunkById(500, function ($rows) {
foreach ($rows as $row) {
$row->update([
'email' => fake()->unique()->safeEmail(),
'name' => fake()->name(),
]);
}
});
This is a few dozen lines and gives you full control over FK ordering, batching, and hashing — usually a better trade than adapting a low-adoption Symfony bundle.
DATABASE_URL in the environment you're running in — a .env mistake here is the classic incident.safeEmail on a password column breaks logins in a way that looks like a bug. Either leave hash columns untouched or map them to a fixed known hash so testers can log in.UPDATE ... SET col = ... or batch by ID range if the bundle supports it.composer why-not and composer audit after install, and read the source of the command before running it — it's small, and you'll want to know exactly which tables it touches.-vvv first against a copied table and diff a few rows before and after to confirm the mapping you wrote is the mapping it applied. Config key typos often fail silently with "no anonymizers configured" rather than throwing.is_test = 0). The latter usually means wrapping the command rather than fighting the bundle's config.How can I help you explore Laravel packages today?