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

Eloquent Mutators Laravel Package

adrolli/eloquent-mutators

Define reusable Eloquent accessors and mutators outside your models. Apply the same transformation logic across multiple models or multiple attributes on one model using a base model class or a trait, with config and extensible registration via a service provider.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require awobaz/eloquent-mutators
    php artisan mutators:install
    
    • This publishes the config file (config/mutators.php) and registers the service provider.
  2. Model Integration: Choose one of these approaches:

    • Extend the base model:
      use Awobaz\Mutator\Database\Eloquent\Model;
      
      class Post extends Model { ... }
      
    • Use the Mutable trait:
      use Awobaz\Mutator\Mutable;
      
      class Post extends \Illuminate\Database\Eloquent\Model {
          use Mutable;
      }
      
  3. First Use Case: Define accessors/mutators in your model:

    protected $accessors = [
        'title' => 'trim_whitespace',
    ];
    

    Now, $post->title will automatically trim whitespace when accessed.


Implementation Patterns

Common Workflows

  1. Reusable Transformations:

    • Centralize logic (e.g., slug generation) in a shared mutator:
      protected $accessors = [
          'slug' => 'slug',
          'meta_title' => 'title_case',
      ];
      
  2. Dynamic Mutators:

    • Use closures for complex logic:
      Mutator::extend('custom_logic', function ($model, $value, $key) {
          return $value * $model->price_multiplier;
      });
      
    • Apply with parameters:
      protected $accessors = [
          'discounted_price' => ['custom_logic' => ['price_multiplier' => 0.9]],
      ];
      
  3. Conditional Mutators:

    • Combine with Laravel’s getAttribute() for conditional logic:
      public function getTitleAttribute($value) {
          return $this->title_trimmed ?? trim($value);
      }
      protected $accessors = ['title_trimmed' => 'trim_whitespace'];
      
  4. Bulk Model Processing:

    • Apply mutators to collections:
      $posts = Post::all()->map(function ($post) {
          return $post->fresh(); // Re-fetch to trigger accessors
      });
      
  5. API Responses:

    • Use mutators to format JSON responses:
      protected $accessors = [
          'formatted_name' => ['capitalize_words', 'slug'],
      ];
      return $post->only(['formatted_name']);
      

Integration Tips

  • Testing: Mock the Mutator facade to test isolated mutator logic:
    $this->mock(Mutator::class)->shouldReceive('applyAccessors');
    
  • Caching: Cache transformed values (e.g., slugs) to avoid repeated processing:
    Mutator::extend('cached_slug', function ($model, $value) {
        return $model->cache->remember("slug_{$value}", now()->addHours(1), function () use ($value) {
            return Str::slug($value);
        });
    });
    
  • Validation: Use mutators to standardize input before validation:
    protected $mutators = [
        'email' => 'lower_case',
    ];
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies:

    • Avoid mutators that reference other mutators (e.g., titleslugtitle).
    • Fix: Use getAttribute() for complex dependencies.
  2. Performance Overhead:

    • Mutators run on every access, even in queries. Use sparingly for heavy operations.
    • Fix: Cache results or use getAttribute() for lazy evaluation.
  3. Configuration Conflicts:

    • Custom config keys (e.g., $accessors) may clash with Laravel’s reserved properties.
    • Fix: Override in config/mutators.php:
      'accessors_property' => 'custom_accessors',
      
  4. Parameter Parsing:

    • String syntax ('str_replace:one,two') fails if parameters contain commas.
    • Fix: Use array syntax:
      'content' => ['str_replace' => ['one', 'two']]
      
  5. Trait vs. Base Class:

    • The Mutable trait may conflict with other traits (e.g., SoftDeletes).
    • Fix: Prefer extending Awobaz\Mutator\Database\Eloquent\Model for large projects.

Debugging

  • Log Mutator Calls: Extend the Mutator facade to log inputs/outputs:
    Mutator::extend('debug', function ($model, $value, $key) {
        \Log::debug("Mutator $key: $value");
        return $value;
    });
    
  • Disable Mutators: Temporarily rename $accessors/$mutators to bypass them during debugging.

Extension Points

  1. Custom Mutators:

    • Register dynamic mutators at runtime:
      Mutator::extend('dynamic_mutator', function ($model, $value, $key, $param) {
          return $value . "_$param";
      });
      
    • Apply dynamically:
      $model->setMutator('dynamic_field', 'dynamic_mutator:suffix');
      
  2. Model Events:

    • Trigger mutators on events (e.g., retrieved):
      protected static function booted() {
          static::retrieved(function ($model) {
              $model->refreshMutators();
          });
      }
      
  3. API Resources:

    • Use mutators in toArray() for consistent API responses:
      public function toArray($request) {
          return [
              'title' => $this->title, // Triggers accessors
              'slug' => $this->slug,
          ];
      }
      

Pro Tips

  • Naming Conventions: Prefix custom mutators with your app namespace (e.g., app_slug) to avoid collisions.
  • Documentation: Add PHPDoc comments to mutators for IDE autocompletion:
    /**
     * @mutator Converts text to kebab-case.
     */
    Mutator::extend('kebab_case', ...);
    
  • Testing: Use fresh() to test mutators in isolation:
    $post = Post::find(1)->fresh();
    $this->assertEquals('trimmed-title', $post->title);
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity