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

Laralight Metadata Laravel Package

seyedmr/laralight-metadata

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require seyedmr/laralight-metadata
    php artisan migrate
    
    • The package adds a metadata table via migration (check database/migrations/ for create_metadata_table.php).
  2. First Use Case:

    • Add the HasMeta trait to a model (e.g., User):
      use SeyedMR\LaraliteMetadata\Traits\HasMeta;
      
      class User extends Model
      {
          use HasMeta;
      }
      
    • Run migrations to create the metadata table.
  3. Basic CRUD:

    • Set metadata:
      $user = User::find(1);
      $user->setMeta('profile.bio', 'Laravel Developer');
      $user->save(); // Required to persist metadata
      
    • Get metadata:
      $bio = $user->getMeta('profile.bio'); // Returns 'Laravel Developer'
      
    • Check existence:
      if ($user->hasMeta('profile.bio')) { ... }
      

Where to Look First

  • Migration: Verify database/migrations/create_metadata_table.php for schema (default: model_type, model_id, key, value).
  • Trait Methods: Explore HasMeta trait in vendor/seyedmr/laralight-metadata/src/Traits/HasMeta.php for all available methods (setMeta, getMeta, hasMeta, deleteMeta, clearMeta).
  • Service Provider: Check config/laralight-metadata.php (if auto-generated) for customization options.

Implementation Patterns

Core Workflows

1. Model-Specific Metadata

  • Use Case: Storing user-specific settings, profile attributes, or dynamic configurations.
  • Pattern:
    // Set nested metadata (dot notation)
    $user->setMeta('preferences.notifications', 'email');
    $user->setMeta('profile.avatar', $avatarPath);
    $user->save();
    
    // Retrieve nested values
    $notifications = $user->getMeta('preferences.notifications');
    
  • Tip: Use dot notation (key.subkey) for hierarchical data.

2. Dynamic Metadata for API Responses

  • Use Case: Customizing API responses based on metadata (e.g., hiding fields for admins).
  • Pattern:
    $user = User::find(1);
    $responseData = $user->toArray();
    
    if ($user->hasMeta('api.hide_email')) {
        unset($responseData['email']);
    }
    return response()->json($responseData);
    

3. Bulk Metadata Operations

  • Use Case: Updating metadata for multiple records (e.g., adding a "featured" flag to products).
  • Pattern:
    $featuredProducts = Product::where('category', 'sale')->get();
    foreach ($featuredProducts as $product) {
        $product->setMeta('promotion.featured', true);
        $product->save();
    }
    
  • Optimization: Use DB::transaction() for batch operations to avoid N+1 queries.

4. Integration with Observers/Events

  • Use Case: Automatically setting metadata on model events (e.g., created, updated).
  • Pattern:
    // app/Observers/UserObserver.php
    public function created(User $user)
    {
        $user->setMeta('created_via', 'api');
        $user->save();
    }
    
    Register the observer in AppServiceProvider@boot():
    User::observe(UserObserver::class);
    

5. Query Scoping with Metadata

  • Use Case: Filtering models based on metadata (e.g., find all users with premium status).
  • Pattern:
    // Create a scope (add to User model)
    public function scopePremium($query)
    {
        return $query->whereHas('metadata', function ($q) {
            $q->where('key', 'status')
              ->where('value', 'premium');
        });
    }
    
    Usage:
    $premiumUsers = User::premium()->get();
    

Advanced Patterns

1. Metadata Serialization

  • Use Case: Storing complex data (e.g., JSON, arrays) in metadata.
  • Pattern:
    $user->setMeta('settings', json_encode(['theme' => 'dark', 'font_size' => 14]));
    $settings = json_decode($user->getMeta('settings'), true);
    

2. Metadata Validation

  • Use Case: Ensuring metadata adheres to rules (e.g., email must be valid).
  • Pattern:
    use Illuminate\Support\Facades\Validator;
    
    public function setMeta($key, $value)
    {
        if ($key === 'contact.email') {
            $validator = Validator::make(['email' => $value], ['email' => 'email']);
            if ($validator->fails()) {
                throw new \Exception('Invalid email format');
            }
        }
        parent::setMeta($key, $value);
    }
    

3. Caching Metadata

  • Use Case: Reducing database hits for frequently accessed metadata.
  • Pattern:
    public function getMeta($key)
    {
        return cache()->remember("meta_{$this->id}_{$key}", now()->addHours(1), function () {
            return parent::getMeta($key);
        });
    }
    

Gotchas and Tips

Pitfalls

  1. Missing save() After setMeta:

    • Issue: Metadata won’t persist without calling $model->save().
    • Fix: Always save the model after modifying metadata:
      $user->setMeta('key', 'value');
      $user->save(); // Critical!
      
  2. Case Sensitivity in Keys:

    • Issue: Metadata keys are case-sensitive ('Key''key').
    • Fix: Standardize key casing (e.g., snake_case) in your application.
  3. No Built-in Encryption:

    • Issue: Metadata values are stored in plaintext.
    • Fix: Encrypt sensitive data before storing:
      use Illuminate\Support\Facades\Crypt;
      
      $user->setMeta('api_token', Crypt::encrypt($token));
      $token = Crypt::decrypt($user->getMeta('api_token'));
      
  4. Performance with Large Datasets:

    • Issue: Querying metadata for thousands of records can be slow.
    • Fix: Use database indexes or denormalize metadata into model attributes for critical paths.
  5. No Built-in Soft Deletes:

    • Issue: Deleting a model won’t automatically remove its metadata.
    • Fix: Manually clear metadata in deleted() observer or override delete():
      public function delete()
      {
          $this->clearMeta();
          parent::delete();
      }
      

Debugging Tips

  1. Check the metadata Table:

    • Verify data exists:
      php artisan tinker
      >>> \DB::table('metadata')->where('model_type', 'App\User')->get();
      
  2. Enable Query Logging:

    • Debug slow metadata queries:
      \DB::enableQueryLog();
      $user->getMeta('key');
      \DB::getQueryLog(); // Inspect queries
      
  3. Validate Trait Usage:

    • Ensure the trait is correctly added to the model and the metadata table exists.

Extension Points

  1. Custom Storage Engine:

    • Override the default metadata table by publishing the config:
      php artisan vendor:publish --provider="SeyedMR\LaraliteMetadata\LaraliteMetadataServiceProvider"
      
    • Modify config/laralight-metadata.php to use a different table or connection.
  2. Add Metadata Scopes:

    • Extend the trait to support custom scopes:
      // In HasMeta trait
      public function scopeWithMeta($query, $key, $value)
      {
          return $query->whereHas('metadata', function ($q) use ($key, $value) {
              $q->where('key', $key)->where('value', $value);
          });
      }
      
      Usage:
      User::withMeta('status', 'active')->get();
      
  3. Event Dispatching:

    • Trigger events when metadata changes:
      // In HasMeta trait
      protected function fireMetaEvents($key, $value)
      {
          event(new MetaUpdated($this, $key, $value));
      }
      
  4. Mass Assignment Protection:

    • Prevent mass assignment of metadata keys:
      protected $metaFillable = ['profile.*', 'settings.*'];
      
      Then override setMeta to validate against `$metaFill
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.
babenkoivan/elastic-client
innmind/static-analysis
innmind/coding-standard
datacore/hub-sdk
alengo/sulu-http-cache-bundle
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity