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

Characteristics Laravel Package

ekyna/characteristics

Laravel package for managing entity characteristics: define reusable attributes, groups and values, attach them to models, and handle normalization/validation for consistent storage and querying across your application.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require ekyna/characteristics
    

    Publish the migration (if needed):

    php artisan vendor:publish --provider="Ekyna\Characteristics\CharacteristicsServiceProvider" --tag="migrations"
    php artisan migrate
    
  2. Basic Model Integration Add the HasCharacteristics trait to your Eloquent model:

    use Ekyna\Characteristics\Traits\HasCharacteristics;
    
    class Product extends Model
    {
        use HasCharacteristics;
    }
    
  3. Define Characteristics Create a characteristics table entry (manually or via migration) for each feature (e.g., color, size). Example:

    $characteristic = \Ekyna\Characteristics\Models\Characteristic::create([
        'name' => 'color',
        'type' => 'string', // or 'boolean', 'number', 'select'
        'options' => json_encode(['red', 'blue', 'green']), // for 'select' type
    ]);
    
  4. Assign Characteristics to an Entity

    $product = Product::find(1);
    $product->characteristics()->attach([
        $characteristic->id => ['value' => 'blue'], // for 'string'/'number'
        // OR for boolean: ['value' => true]
        // OR for select: ['value' => 'red']
    ]);
    
  5. Retrieve Characteristics

    $product->characteristics; // Collection of Characteristic models
    $product->getCharacteristic('color'); // Returns 'blue' (or null)
    

Implementation Patterns

Common Workflows

  1. Dynamic Filtering Use characteristics to filter entities in queries:

    $blueProducts = Product::whereHas('characteristics', function ($query) {
        $query->where('name', 'color')
              ->where('value', 'blue');
    })->get();
    
  2. Validation Rules Leverage characteristics in Form Requests:

    use Ekyna\Characteristics\Rules\CharacteristicExists;
    
    public function rules()
    {
        return [
            'characteristics.color' => ['required', new CharacteristicExists('color')],
        ];
    }
    
  3. API Responses Serialize characteristics in JSON:

    return Product::with('characteristics')->get()->map(function ($product) {
        return [
            'id' => $product->id,
            'characteristics' => $product->characteristics->pluck('name', 'value'),
        ];
    });
    
  4. Bulk Updates Update characteristics for multiple entities:

    $products = Product::whereIn('id', [1, 2, 3])->get();
    foreach ($products as $product) {
        $product->characteristics()->sync([
            $characteristic->id => ['value' => 'updated_value'],
        ]);
    }
    

Integration Tips

  • Polymorphic Relationships Extend the package to support polymorphic characteristics (e.g., for Product and User):

    // In CharacteristicsServiceProvider boot():
    $this->app->bind('characteristicable', function () {
        return config('characteristics.polymorphic_model', null);
    });
    
  • Caching Cache characteristic queries for performance:

    $characteristics = Cache::remember("product_{$product->id}_characteristics", now()->addHours(1), function () use ($product) {
        return $product->characteristics;
    });
    
  • Events Listen for characteristic changes:

    \Ekyna\Characteristics\Models\Characteristic::saved(function ($characteristic) {
        // Log or notify when a characteristic is updated
    });
    

Gotchas and Tips

Pitfalls

  1. Missing Migrations

    • Forgetting to run migrations after installation will cause Characteristic model errors.
    • Fix: Always run php artisan migrate post-install.
  2. Type Mismatches

    • Storing a string value in a number or boolean characteristic field will silently fail or corrupt data.
    • Fix: Validate input before attaching:
      if ($characteristic->type === 'number' && !is_numeric($value)) {
          throw new \InvalidArgumentException("Value must be numeric for {$characteristic->name}");
      }
      
  3. Overwriting Values

    • Using sync() or attach() without preserving existing values will overwrite them.
    • Fix: Use syncWithoutDetaching() or manually merge values:
      $existing = $product->characteristics->pluck('value', 'id')->toArray();
      $product->characteristics()->sync(array_merge($existing, [$newId => ['value' => $newValue]]));
      
  4. Case Sensitivity

    • select type options are case-sensitive by default. E.g., 'Red''red'.
    • Fix: Normalize options or values:
      $options = array_map('strtolower', json_decode($characteristic->options, true));
      
  5. Performance with Large Datasets

    • Querying characteristics for thousands of entities can be slow.
    • Fix: Use with() to eager-load:
      $products = Product::with('characteristics')->get();
      

Debugging Tips

  • Check Database Verify characteristics are stored correctly:

    SELECT * FROM characteristics;
    SELECT * FROM characteristicables;
    
  • Log Characteristic Attachments Debug sync issues:

    \Ekyna\Characteristics\Models\Characteristic::saved(function ($characteristic) {
        \Log::debug("Characteristic updated: ", [
            'id' => $characteristic->id,
            'value' => $characteristic->pivot->value,
        ]);
    });
    
  • Validate Characteristic Types Ensure the type column in the characteristics table matches your usage (string, boolean, number, select).

Extension Points

  1. Custom Characteristic Types Extend the package to support custom types (e.g., date, json):

    // In app/Providers/CharacteristicsServiceProvider.php
    $this->app->extend('characteristics.types', function ($types) {
        $types['date'] = \Ekyna\Characteristics\Types\DateType::class;
        return $types;
    });
    
  2. Custom Storage Store characteristics in a NoSQL database or cache:

    // Override the pivot model
    class CustomCharacteristicPivot extends \Ekyna\Characteristics\Models\CharacteristicPivot
    {
        public function save(array $options = [])
        {
            // Custom logic (e.g., Redis storage)
            parent::save($options);
        }
    }
    
  3. API Resources Create a dedicated CharacteristicResource for API responses:

    namespace App\Http\Resources;
    
    use Ekyna\Characteristics\Models\Characteristic;
    use Illuminate\Http\Resources\Json\JsonResource;
    
    class CharacteristicResource extends JsonResource
    {
        public function toArray($request)
        {
            return [
                'id' => $this->id,
                'name' => $this->name,
                'type' => $this->type,
                'value' => $this->pivot->value,
                'options' => $this->options,
            ];
        }
    }
    
  4. Scopes for Querying Add reusable scopes to your models:

    class Product extends Model
    {
        use HasCharacteristics;
    
        public function scopeWithCharacteristic($query, $name, $value)
        {
            return $query->whereHas('characteristics', function ($q) use ($name, $value) {
                $q->where('name', $name)
                  ->where('value', $value);
            });
        }
    }
    
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.
andydefer/laravel-actions
aimeos/prisma
besmartand-pro/php-quality-config
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
christhompsontldr/laravel-inky
spatie/mailcoach-vapor