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

Laravel Custom Fields Laravel Package

onramplab/laravel-custom-fields

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require onramplab/laravel-custom-fields
    php artisan vendor:publish --provider="OnrampLab\CustomFields\CustomFieldsServiceProvider" --tag="migrations"
    php artisan migrate
    

    Run migrations to set up the custom_fields and custom_field_values tables.

  2. Define a Model: Use the HasCustomFields trait in your Eloquent model:

    use OnrampLab\CustomFields\Traits\HasCustomFields;
    
    class Product extends Model
    {
        use HasCustomFields;
    }
    
  3. First Use Case: Add a custom field dynamically to a Product instance:

    $product = Product::first();
    $product->addCustomField('color', 'text', 'Red');
    $product->save();
    

    Retrieve the value:

    $color = $product->getCustomField('color');
    

Where to Look First

  • Migrations: Check database/migrations/ for the schema structure.
  • Traits & Interfaces: Review HasCustomFields and CustomFieldable in the package source.
  • Service Provider: Inspect CustomFieldsServiceProvider for bootstrapping logic.
  • API Docs: Focus on CustomField and CustomFieldValue classes for core functionality.

Implementation Patterns

Core Workflows

  1. Dynamic Field Management:

    • Adding Fields:
      $model->addCustomField('field_key', 'field_type', $value);
      
      Types: text, integer, float, datetime, select, boolean, rich_text.
    • Bulk Operations:
      $model->addCustomFields([
          'price' => ['type' => 'float', 'value' => 19.99],
          'is_featured' => ['type' => 'boolean', 'value' => true],
      ]);
      
  2. Polymorphic Associations:

    • Attach fields to any model supporting HasCustomFields:
      $user = User::find(1);
      $user->addCustomField('preference', 'text', 'Dark Mode');
      
    • Retrieve fields across models:
      $fields = CustomField::where('field_key', 'preference')->get();
      
  3. Validation & Defaults:

    • Set defaults in config/custom-fields.php:
      'defaults' => [
          'field_types' => ['text', 'integer', 'select'],
      ],
      
    • Validate fields before saving:
      $model->validateCustomFields([
          'field_key' => 'required|string',
      ]);
      
  4. Querying Custom Fields:

    • Filter models by custom field values:
      $products = Product::whereHasCustomField('color', 'Red')->get();
      
    • Get all fields for a model:
      $fields = $model->getCustomFields();
      

Integration Tips

  • Admin Panels: Use the package to build flexible CMS-like interfaces (e.g., Laravel Nova/Voyager plugins).
  • APIs: Dynamically expose custom fields in API responses:
    return $model->append(['custom_fields']);
    
  • Events: Listen for CustomFieldCreated, CustomFieldUpdated, etc., via:
    event(new CustomFieldCreated($model, $field));
    
  • Caching: Cache frequent custom field queries:
    Cache::remember("model_{$model->id}_fields", now()->addHours(1), fn() => $model->getCustomFields());
    

Gotchas and Tips

Pitfalls

  1. Polymorphic Conflicts:

    • Ensure custom_fields table has a unique field_key per model type (e.g., products_color vs. users_preference). Overlapping keys may cause silent failures.
    • Fix: Use a composite unique key (model_type, field_key) or prefix keys with the model class name.
  2. Field Type Mismatches:

    • Storing a string in an integer field may corrupt data. Validate types strictly:
      if (!$model->validateCustomFieldType('age', 'integer')) {
          throw new \InvalidArgumentException("Field 'age' must be an integer.");
      }
      
  3. Mass Assignment Risks:

    • Custom fields bypass Laravel’s $fillable. Explicitly whitelist safe fields:
      protected $customFieldWhitelist = ['metadata.*', 'settings.*'];
      
  4. Performance with Large Datasets:

    • Avoid getCustomFields() in loops. Use eager loading:
      $models = Model::withCustomFields()->get();
      

Debugging

  • Missing Fields:

    • Check if the custom_fields table has entries for your model. Run:
      php artisan tinker
      >>> \OnrampLab\CustomFields\CustomField::where('field_key', 'missing_field')->get();
      
    • Verify the model_type column matches your model’s class name (e.g., App\Models\Product).
  • Serialization Issues:

    • Complex values (e.g., arrays) may not serialize/deserialize correctly. Use json type or encode manually:
      $model->addCustomField('tags', 'json', json_encode(['tag1', 'tag2']));
      $tags = json_decode($model->getCustomField('tags'), true);
      

Extension Points

  1. Custom Field Types:

    • Extend OnrampLab\CustomFields\FieldTypes\FieldType to add support for new types (e.g., image, file):
      class ImageFieldType extends FieldType
      {
          public function validate($value) { /* ... */ }
          public function serialize($value) { /* ... */ }
      }
      
    • Register in config/custom-fields.php:
      'field_types' => [
          'image' => \App\FieldTypes\ImageFieldType::class,
      ],
      
  2. Field Value Accessors:

    • Override getCustomFieldAttribute in your model:
      public function getCustomFieldAttribute($key)
      {
          $value = parent::getCustomFieldAttribute($key);
          return $key === 'price' ? '$' . $value : $value;
      }
      
  3. Scopes:

    • Add global query scopes to CustomField:
      class CustomFieldScope
      {
          public function scopeActive($query)
          {
              return $query->where('is_active', true);
          }
      }
      
    • Register in CustomFieldsServiceProvider.
  4. Migration Hooks:

    • Listen for CustomFieldCreating events to enforce naming conventions:
      CustomField::creating(function ($field) {
          $field->field_key = strtolower($field->field_key);
      });
      

Config Quirks

  • Default Values:
    • Set defaults in config/custom-fields.php:
      'defaults' => [
          'field_types' => ['text', 'integer', 'select'],
          'validation_rules' => [
              'text' => 'nullable|string|max:255',
              'select' => 'required|in:option1,option2',
          ],
      ],
      
  • Polymorphic Key:
    • Customize the polymorphic key if needed:
      'polymorphic_key' => 'customizable_key', // Default: 'model_type'
      

Pro Tips

  • Bulk Updates: Use updateCustomField for atomic updates:
    $model->updateCustomField('price', 29.99);
    
  • Field Descriptions: Store metadata in a description column or use a separate custom_field_metadata table.
  • Soft Deletes: Enable soft deletes for custom fields:
    use SoftDeletes;
    class CustomField extends Model { use SoftDeletes; }
    
    Update migrations accordingly.
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.
cadot.eu/make
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
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