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

Activeredis Laravel Package

directorytree/activeredis

Active Record-style Redis hash models for Laravel. Create, update, delete, expire, and query Redis-backed records with an Eloquent-like API, including model identifiers, timestamps, casts, events, connections, chunking, searching, and testing support.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Steps
1. **Installation**:
   ```bash
   composer require directorytree/activeredis

Ensure your config/database.php has a dedicated Redis connection for ActiveRedis (recommended).

  1. Define a Model:

    namespace App\Redis;
    use DirectoryTree\ActiveRedis\Model;
    
    class Visit extends Model {}
    
  2. Create a Record:

    $visit = Visit::create([
        'ip' => '192.168.1.1',
        'url' => 'https://example.com',
    ]);
    
  3. Query a Record:

    $visit = Visit::find('f195637b-7d48-43ab-abab-86e93dfc9410');
    

First Use Case

Track User Visits with Optimized Performance:

// Create a visit record (now with optimized Redis pipelining under the hood)
$visit = Visit::create([
    'ip' => request()->ip(),
    'url' => request()->url(),
    'user_agent' => request()->userAgent(),
]);

// Later, retrieve all visits (attribute fetching is now pipelined)
$visits = Visit::query()->get();

Where to Look First

  • Model Definition: app/Redis/Visit.php (or your custom model file).
  • Configuration: config/database.php (Redis connection).
  • Searchable Attributes: Define in your model ($searchable).
  • Events: Hook into lifecycle events in the booted() method.
  • Pipeline Optimization: Understand how attribute fetching now uses Redis pipelines (see Implementation Patterns).

Implementation Patterns

Core Workflows

1. CRUD Operations

  • Create:
    $model = ModelName::create(['key' => 'value']);
    
  • Read (now optimized with pipelining):
    $model = ModelName::find('id');
    // Or query all (attributes fetched in bulk)
    $models = ModelName::all();
    
  • Update:
    $model->update(['key' => 'new_value']);
    // Or
    $model->key = 'new_value';
    $model->save();
    
  • Delete:
    $model->delete();
    // Or bulk delete
    ModelName::destroy(['id1', 'id2']);
    

2. Expiring Models

  • Set expiry on creation or later:
    $model = ModelName::create(['key' => 'value']);
    $model->setExpiry(now()->addHours(1));
    
  • Check expiry:
    if ($model->getExpiry()) {
        // Model will expire at $model->getExpiry()
    }
    

3. Searching

  • Define searchable attributes in your model:
    class Visit extends Model {
        protected array $searchable = ['ip', 'url'];
    }
    
  • Search dynamically (now benefits from pipelined attribute fetching):
    $results = ModelName::search('ip', '192.168.1.1')->get();
    

4. Chunking for Large Datasets

  • Process records in batches to avoid memory issues (pipelining helps reduce overhead):
    ModelName::chunk(100, function ($models) {
        foreach ($models as $model) {
            // Process each model (attributes fetched efficiently)
        }
    });
    

5. Custom Key Generation

  • Override getNewKey() for non-UUID keys:
    protected function getNewKey(): string {
        return Str::random(20);
    }
    

6. Leveraging Pipeline Optimization

  • The package now uses Redis pipelines for attribute fetching, reducing round trips. This is automatic for all find(), all(), and query operations.
  • Example: Fetching 100 models with 5 attributes each now requires ~2 Redis calls (vs ~500 before):
    $models = ModelName::limit(100)->get(); // Attributes fetched in bulk
    

Integration Tips

1. Separate Redis Connection

  • Configure a dedicated Redis connection in config/database.php for ActiveRedis to avoid scanning unrelated keys (e.g., cache, sessions).
  • Example:
    'activeredis' => [
        'url' => env('REDIS_URL'),
        'database' => 10, // Isolated database
    ],
    

2. Events and Observers

  • Use observers for cross-cutting concerns (e.g., logging, analytics):
    // app/Observers/VisitObserver.php
    class VisitObserver {
        public function created(Visit $visit) {
            Log::info("New visit recorded: {$visit->ip}");
        }
    }
    
  • Register in AppServiceProvider:
    Visit::observe(VisitObserver::class);
    

3. Casts for Type Safety

  • Define casts to avoid manual type conversion (pipelining applies to casted attributes too):
    class Visit extends Model {
        protected array $casts = [
            'user_id' => 'integer',
            'is_bot' => 'boolean',
            'metadata' => 'json',
        ];
    }
    

4. Dynamic Query Building

  • Leverage Eloquent-like query methods (now with optimized attribute fetching):
    $recentVisits = Visit::where('created_at', '>', now()->subHours(1))->get();
    

5. Testing Pipeline Behavior

  • Mock Redis pipelines in tests to verify optimization:
    use DirectoryTree\ActiveRedis\Facades\ActiveRedis;
    
    public function test_pipelined_attribute_fetching() {
        ActiveRedis::shouldReceive('pipeline')
                    ->once()
                    ->andReturnSelf()
                    ->shouldReceive('hGetAll')
                    ->with('visits:id:test-key')
                    ->once()
                    ->andReturn(['ip' => '192.168.1.1']);
    
        $model = ModelName::find('test-key');
        $this->assertEquals('192.168.1.1', $model->ip);
    }
    

Gotchas and Tips

Pitfalls

1. Case Sensitivity in Keys

  • Redis keys are case-sensitive. Ensure consistency when defining keys (e.g., id vs ID).
  • Example:
    // Fails to find the model if case doesn't match
    $model = ModelName::find('CUSTOM-ID'); // Returns null if stored as 'custom-id'
    

2. Searchable Attributes Are Immutable

  • Changing $searchable after records exist will break searches. Plan schema early.
  • Workaround: Use a separate Redis hash for searchable fields if flexibility is needed.

3. Chunking Limitations

  • Redis SCAN does not guarantee exact batch sizes. Use each() with a callback to handle variability:
    ModelName::each(function ($model) {
        // Process model (attributes fetched per batch)
    }, 100); // Batch size hint
    

4. Force Overwrite Risks

  • Using force: true in create() or save() deletes existing records silently. Document this behavior in your code.
  • Example:
    // Deletes existing record if it exists
    ModelName::create(['id' => '123'], force: true);
    

5. Expiry and Deletion Race Conditions

  • If a model expires while being accessed, it may return null unexpectedly. Handle gracefully:
    $model = ModelName::find('id');
    if (!$model) {
        // Handle expired/deleted model
    }
    

6. Reserved Characters in Keys

  • Avoid colons (:) and asterisks (*) in custom keys or searchable values. Redis uses these for patterns.

7. Pipeline Overhead for Small Datasets

  • While pipelining is optimized, very small datasets (e.g., single-record queries) may see negligible benefits. Focus optimization on bulk operations.

Debugging Tips

1. Check Redis Keys Manually

  • Use redis-cli to inspect keys:
    redis-cli KEYS "visits:id:*"
    
  • Verify expiry with:
    redis-cli TTL "visits:id:f195637b-7d48-43ab-abab-86e93dfc9410"
    

2. Enable Query Logging

  • Temporarily log queries in AppServiceProvider to see pipeline usage:
    use DirectoryTree\ActiveRedis\Facades\ActiveRedis;
    
    public function boot() {
        ActiveRedis::setLogger(function
    
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.
boundwize/jsonrecast
codraw/graphviz
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
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