Weave Code
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

Anonymize Laravel Package

directorytree/anonymize

Anonymize swaps sensitive Eloquent model attributes with realistic Faker data. Deterministic per model ID, cached for performance, and easy to toggle globally or per instance—ideal for dev, demos, and safely sharing production-like datasets.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require directorytree/anonymize
    

    Ensure your project meets the requirements (PHP 8.2+, Laravel 11+).

  2. Enable Anonymization: Add this to a service provider (e.g., AppServiceProvider):

    use DirectoryTree\Anonymize\Facades\Anonymize;
    
    public function boot(): void
    {
        if (session('anonymize')) {
            Anonymize::enable();
        }
    }
    
  3. First Use Case: Anonymize a User model for a demo environment:

    // app/Models/User.php
    use DirectoryTree\Anonymize\{Anonymizable, Anonymized};
    
    class User extends Model implements Anonymizable
    {
        use Anonymized;
    
        public function getAnonymizedAttributes(Generator $faker): array
        {
            return [
                'name' => $faker->name(),
                'email' => $faker->safeEmail(),
            ];
        }
    }
    

    Now, when Anonymize::enable() is called, User instances will return fake data for name and email.


Implementation Patterns

Core Workflow

  1. Model Integration:

    • Implement Anonymizable interface and use Anonymized trait.
    • Define sensitive attributes in getAnonymizedAttributes() with Faker-generated values.
    • Example:
      public function getAnonymizedAttributes(Generator $faker): array
      {
          return [
              'credit_card' => $faker->creditCardNumber(),
              'ssn' => $faker->nineDigitNumber(),
          ];
      }
      
  2. Conditional Anonymization:

    • Dynamically control which attributes to anonymize based on logic (e.g., roles, environments):
      public function getAnonymizedAttributes(Generator $faker): array
      {
          $attributes = ['email' => $faker->safeEmail()];
          if (app()->environment('local')) {
              $attributes['password'] = '********';
          }
          return $attributes;
      }
      
  3. Resource Anonymization:

    • Extend JSON resources for API responses:
      use DirectoryTree\Anonymize\AnonymizedResource;
      
      class UserResource extends JsonResource implements Anonymizable
      {
          use AnonymizedResource;
      
          public function toArray(Request $request): array
          {
              return $this->toAnonymized([
                  'id', 'name', 'email', // Only these fields are exposed
              ]);
          }
      
          public function getAnonymizedAttributes(Generator $faker): array
          {
              return ['name' => $faker->name()];
          }
      }
      
  4. Global Control:

    • Toggle anonymization via facade or middleware:
      // Middleware: Enable for demo routes
      public function handle(Request $request, Closure $next)
      {
          Anonymize::enable();
          return $next($request);
      }
      
  5. Consistency:

    • Override getAnonymizableSeed() for deterministic fake data:
      public function getAnonymizableSeed(): string
      {
          return "user:{$this->id}:{$this->email}";
      }
      

Integration Tips

  • Testing: Use Anonymize::enable() in test environments to avoid exposing real data:
    public function test_user_anonymization()
    {
        Anonymize::enable();
        $user = User::find(1);
        $this->assertNotEquals($user->email, 'real@example.com');
    }
    
  • Caching: The package caches fake data by default. Clear cache if seeds change:
    Anonymize::clearCache();
    
  • Events: Listen for anonymize.enabled/anonymize.disabled events to trigger side effects (e.g., logging, notifications).

Gotchas and Tips

Pitfalls

  1. Static State:

    • The Anonymize facade maintains static state. Ensure it’s reset between tests or requests if needed:
      Anonymize::disable(); // Reset after tests
      
    • Fix: Use Anonymize::flush() to clear cached data.
  2. Nested Resources:

    • Deeply nested JsonResource anonymization may require explicit configuration. Ensure parent resources delegate to child resources:
      // ParentResource.php
      public function toArray(Request $request): array
      {
          return $this->toAnonymized([
              'id',
              'children' => $this->whenLoaded('children', function () {
                  return $this->children->map(fn ($child) => new ChildResource($child));
              }),
          ]);
      }
      
  3. Seed Collisions:

    • Custom seeds must be unique per model instance to avoid duplicate fake data. Use composite keys (e.g., user:{id}:{email}) for reliability.
  4. Performance:

    • Heavy anonymization (e.g., large datasets) may impact performance. Benchmark with phpbench and optimize seeds or caching.
  5. Faker Locale:

    • Faker’s locale affects generated data (e.g., en_US vs. ja_JP). Set it globally in config/app.php or per instance:
      $faker = Faker\Factory::create('ja_JP');
      

Debugging

  • Verify Anonymization: Check if a model is anonymized:
    $user = User::find(1);
    dd($user->isAnonymized()); // true/false
    
  • Inspect Fake Data: Log the generated seed and attributes:
    public function getAnonymizedAttributes(Generator $faker): array
    {
        logger()->debug("Seed: {$this->getAnonymizableSeed()}");
        return [...];
    }
    
  • Clear Cache: If fake data appears stale, clear the cache:
    php artisan anonymize:clear-cache
    

Extension Points

  1. Custom Faker Providers: Extend Faker with domain-specific providers (e.g., fakeCompanyName()):

    $faker->addProvider(new CustomFakerProvider($faker));
    

    Inject the extended Faker into getAnonymizedAttributes().

  2. Dynamic Attribute Mapping: Use closures for dynamic anonymization logic:

    public function getAnonymizedAttributes(Generator $faker): array
    {
        return collect($this->getDirty())
            ->filter(fn ($value, $key) => str_contains($key, 'sensitive_'))
            ->mapWithKeys(fn ($value, $key) => [
                $key => $faker->{$this->getFakeMethod($key)}()
            ])->toArray();
    }
    
  3. Anonymization Policies: Create a policy-based system to centralize rules:

    class UserAnonymizationPolicy
    {
        public function shouldAnonymize(User $user, string $attribute): bool
        {
            return $user->isPublic() && in_array($attribute, ['email', 'phone']);
        }
    }
    

    Integrate via getAnonymizedAttributes():

    public function getAnonymizedAttributes(Generator $faker): array
    {
        $policy = app(UserAnonymizationPolicy::class);
        return collect($this->attributes)
            ->filter(fn ($value, $key) => $policy->shouldAnonymize($this, $key))
            ->mapWithKeys(fn ($value, $key) => [$key => $faker->safeEmail()])
            ->toArray();
    }
    
  4. Event-Driven Anonymization: Trigger anonymization on model events (e.g., retrieved):

    protected static function booted()
    {
        static::retrieved(function ($model) {
            if (Anonymize::isEnabled()) {
                $model->anonymize();
            }
        });
    }
    

Configuration Quirks

  • Facade Binding: The facade binds to the anonymize service container key. Override bindings if extending:
    $this->app->bind('anonymize', function () {
        return new CustomAnonymizeManager();
    });
    
  • Environment-Specific: Enable anonymization only in specific environments (e.g., local, staging):
    if (in_array(app()->environment(), ['local', 'staging'])) {
        Anonymize::enable();
    }
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport
twbs/bootstrap4