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 Meta Laravel Package

phoenix/eloquent-meta

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require phoenix/eloquent-meta
    

    For Laravel 5.7+:

    composer require phoenix/eloquent-meta:^1.9
    
  2. Publish Migrations (if using Laravel):

    php artisan vendor:publish --provider="Phoenix\EloquentMeta\EloquentMetaServiceProvider" --tag="migrations"
    

    Run migrations:

    php artisan migrate
    
  3. Basic Usage:

    use Phoenix\EloquentMeta\EloquentMetaTrait;
    
    class Post extends Model
    {
        use EloquentMetaTrait;
    }
    
    // Set meta
    $post = Post::find(1);
    $post->setMeta(['author' => 'John Doe', 'views' => 100]);
    
    // Get meta
    $author = $post->getMeta('author');
    

First Use Case

Store and retrieve dynamic metadata for a User model (e.g., last_login_ip, preferences):

$user = User::find(1);
$user->setMeta(['last_login_ip' => request()->ip(), 'theme' => 'dark']);
$theme = $user->getMeta('theme', 'light'); // Fallback to 'light'

Implementation Patterns

Core Workflows

1. Model Integration

  • Trait Usage: Add use EloquentMetaTrait; to any Eloquent model.
  • Custom Table: Override the default meta table name via the $metaTable property:
    class Post extends Model
    {
        use EloquentMetaTrait;
    
        protected $metaTable = 'post_metadata';
    }
    

2. CRUD Operations

  • Set Meta:

    // Single key-value
    $post->setMeta('views', 150);
    
    // Multiple key-values
    $post->setMeta(['author' => 'Jane Doe', 'tags' => ['laravel', 'php']]);
    
    // Merge with existing meta
    $post->setMeta(['views' => 150], true); // `true` = merge
    
  • Get Meta:

    // Single key
    $views = $post->getMeta('views');
    
    // Multiple keys
    $data = $post->getMeta(['author', 'tags']);
    
    // Fallback value
    $theme = $post->getMeta('theme', 'default');
    
  • Delete Meta:

    $post->deleteMeta('views'); // Delete single key
    $post->deleteMeta(['author', 'tags']); // Delete multiple keys
    $post->deleteMeta(); // Delete all meta for the model
    

3. Query Scoping

Filter models by meta data using query scopes:

// Find posts with >100 views
$posts = Post::whereMeta('views', '>', 100)->get();

// Find posts with specific tags
$posts = Post::whereMeta('tags', 'like', '%laravel%')->get();

4. Events

Listen for meta changes via events:

// In EventServiceProvider
protected $listen = [
    'Phoenix\EloquentMeta\Events\MetaSaved' => [
        'App\Listeners\LogMetaChanges',
    ],
];

Integration Tips

Laravel-Specific

  • Service Provider: Register the package in config/app.php under providers:
    Phoenix\EloquentMeta\EloquentMetaServiceProvider::class,
    
  • Config: Publish the config file for customization:
    php artisan vendor:publish --provider="Phoenix\EloquentMeta\EloquentMetaServiceProvider" --tag="config"
    
    Customize config/eloquent-meta.php (e.g., default table name, fallback behavior).

Non-Laravel Usage

  • Manual Migration: If not using Laravel, create the meta table manually:
    CREATE TABLE model_meta (
        model_id INTEGER,
        model_type VARCHAR(255),
        key VARCHAR(255),
        value TEXT,
        PRIMARY KEY (model_id, model_type, key)
    );
    
  • Service Container: Bind the trait manually if not using Laravel’s IoC.

Performance

  • Batch Operations: Use setMeta() with arrays for bulk updates.
  • Indexing: Ensure the model_meta table has indexes on (model_id, model_type, key) for faster queries.

Gotchas and Tips

Pitfalls

  1. Laravel Version Compatibility:

    • The package is not actively maintained and may break with Laravel 8/9+. Test thoroughly.
    • For Laravel 8+, consider forking the repo or using alternatives like spatie/laravel-activitylog or stancl/tenancy for meta-like functionality.
  2. Migration Conflicts:

    • If you’ve manually created a model_meta table, the package’s migrations will fail. Either:
      • Delete the existing table and let the package create it.
      • Skip migrations and use the existing table (ensure its schema matches).
  3. Serialization Issues:

    • Complex values (e.g., arrays, objects) are serialized to JSON. Ensure your database supports JSON or TEXT columns.
    • Example of unsupported behavior:
      $post->setMeta('complex', new stdClass()); // May fail silently.
      
  4. Query Scope Limitations:

    • whereMeta() only supports basic comparisons (=, >, <, like). Avoid complex queries like whereMeta('tags', 'json_contains', '["laravel"]').
  5. Model Type Collisions:

    • The model_type column uses the fully qualified class name (e.g., App\Models\Post). Ensure this doesn’t exceed your database’s column length limits (default is often 255 chars).

Debugging

  1. Missing Meta Data:

    • Verify the model_meta table exists and has data:
      SELECT * FROM model_meta WHERE model_id = 1 AND model_type = 'App\Models\Post';
      
    • Check for silent failures by enabling Laravel’s query logging:
      DB::enableQueryLog();
      $post->setMeta('test', 'value');
      dd(DB::getQueryLog());
      
  2. Serialization Errors:

    • Wrap complex values in json_encode() before setting:
      $post->setMeta('tags', json_encode(['laravel', 'php']));
      
    • Retrieve with json_decode():
      $tags = json_decode($post->getMeta('tags'), true);
      
  3. Event Firing:

    • Ensure listeners are registered in EventServiceProvider. Test with:
      event(new \Phoenix\EloquentMeta\Events\MetaSaved($post, ['key' => 'value']));
      

Tips

  1. Fallback Values:

    • Always provide fallback values for getMeta() to avoid null returns:
      $theme = $post->getMeta('theme', 'light'); // Defaults to 'light'
      
  2. Type Safety:

    • Cast meta values explicitly when retrieving:
      $views = (int) $post->getMeta('views', 0);
      
  3. Testing:

    • Use fresh database transactions for meta tests:
      public function test_meta()
      {
          $post = Post::factory()->create();
          $this->actingAs(user())
               ->post('/posts/' . $post->id, ['meta' => ['views' => 100]])
               ->assertOk();
      }
      
  4. Alternatives:

    • For Laravel 8+, consider:
      • Spatie’s Activity Log: For audit trails.
      • JSON Columns: Native Laravel 8+ JSON columns for simple meta storage.
      • Redis: For high-performance, temporary metadata (e.g., cache()->put("post:{$post->id}:meta", $meta)).
  5. Extending Functionality:

    • Override the getMetaTable() method in your model for dynamic table names:
      protected function getMetaTable()
      {
          return "{$this->table}_meta";
      }
      
    • Extend the trait to add custom methods:
      trait ExtendedEloquentMetaTrait
      {
          public function incrementMeta($key, $value = 1)
          {
              $current = $this->getMeta($key, 0);
              $this->setMeta($key, $current + $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.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle