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

spatie/laravel-valuestore

Store and retrieve loose key/value data in a JSON file with a simple API. Supports put/get with defaults, has/all, forget/flush, increment, and helpers like ArrayAccess and Countable—handy for app settings or small persistent state.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-valuestore
    

    Publish the config (optional):

    php artisan vendor:publish --provider="Spatie\Valuestore\ValuestoreServiceProvider"
    
  2. First Use Case: Store and retrieve a simple configuration value:

    use Spatie\Valuestore\Valuestore;
    
    $valuestore = Valuestore::make(storage_path('app/feature_flags.json'));
    $valuestore->put('new_feature_enabled', false);
    $isEnabled = $valuestore->get('new_feature_enabled', false); // Returns `false`
    
  3. Where to Look First:

    • Config: config/valuestore.php (default storage path: storage/valuestore.json).
    • Facade: Valuestore::make() for custom paths or Valuestore::get() for the default store.
    • API Docs: Focus on put(), get(), has(), forget(), and flush() methods.

Implementation Patterns

Core Workflows

  1. Configuration Management:

    // Store app settings (e.g., API keys, feature toggles)
    Valuestore::put('api.key', env('API_KEY'));
    Valuestore::put('features.new_ui', false);
    
    // Retrieve with defaults
    $apiKey = Valuestore::get('api.key', '');
    
  2. Feature Flags:

    // Toggle features dynamically
    if (Valuestore::get('features.dark_mode', false)) {
        // Enable dark mode logic
    }
    
  3. Caching Transient Data:

    // Cache computed results (e.g., expensive API calls)
    $result = Valuestore::get('expensive_result');
    if (!$result) {
        $result = computeExpensiveOperation();
        Valuestore::put('expensive_result', $result, now()->addHours(1)); // TTL
    }
    
  4. Bulk Operations:

    // Initialize default values
    Valuestore::put([
        'user_preferences.theme' => 'light',
        'user_preferences.notifications' => true,
    ]);
    
    // Update multiple keys atomically
    Valuestore::put([
        'user_preferences.theme' => 'dark',
        'user_preferences.language' => 'en',
    ]);
    
  5. Scoped Stores:

    // Use separate stores for different contexts (e.g., per-tenant)
    $tenantStore = Valuestore::make(storage_path("app/tenants/{$tenantId}/config.json"));
    $tenantStore->put('max_connections', 100);
    

Integration Tips

  • Service Providers: Bind the default store in register():

    $this->app->singleton('valuestore', function () {
        return Valuestore::make(config('valuestore.path'));
    });
    

    Then inject via constructor:

    public function __construct(private Valuestore $valuestore) {}
    
  • Artisan Commands: Use the store to persist command state or config:

    $this->valuestore->put('last_run', now());
    
  • Events/Listeners: Update the store in response to events (e.g., user preferences):

    event(new UserPreferenceUpdated($user, 'theme', 'dark'));
    // Listener:
    Valuestore::put("user_{$user->id}_theme", 'dark');
    
  • Testing: Use Valuestore::flush() in setUp() to ensure clean state:

    public function setUp(): void {
        parent::setUp();
        Valuestore::flush();
    }
    

Gotchas and Tips

Pitfalls

  1. File Permissions:

    • Ensure the storage directory (storage/valuestore.json by default) is writable.
    • Debug: chmod -R 755 storage/.
  2. JSON Serialization:

    • Only JSON-serializable data can be stored (no resources, closures, or custom objects without __toString() or JsonSerializable).
    • Workaround: Use json_encode()/json_decode() for complex objects:
      $data = ['user' => $user->toArray()];
      Valuestore::put('user_data', json_encode($data));
      $decoded = json_decode(Valuestore::get('user_data'), true);
      
  3. Race Conditions:

    • The package does not handle concurrent writes atomically. For critical data, use a mutex or database-backed solution.
  4. Default Store Overrides:

    • If you publish the config and set a custom path, ensure the directory exists:
      if (!file_exists(config('valuestore.path'))) {
          file_put_contents(config('valuestore.path'), '{}');
      }
      
  5. TTL (Time-to-Live) Quirks:

    • The put() method accepts a TTL (3rd argument), but no automatic cleanup occurs. Implement a cron job or use Laravel's schedule:
      // In App\Console\Kernel.php
      $schedule->command('valuestore:cleanup')->hourly();
      
      Then create a command to delete expired keys.

Debugging

  1. Inspect the File:

    • Directly check storage/valuestore.json (or your custom path) for stored data.
  2. Logging:

    • Wrap operations in try-catch to log serialization errors:
      try {
          Valuestore::put('complex_data', $object);
      } catch (\Throwable $e) {
          Log::error("Valuestore error: " . $e->getMessage());
      }
      
  3. Validation:

    • Validate keys before storing to avoid typos:
      $key = 'features.new_ui';
      if (!preg_match('/^[a-z0-9_\.]+$/i', $key)) {
          throw new \InvalidArgumentException("Invalid key format");
      }
      

Extension Points

  1. Custom Storage Backends:

    • Extend Spatie\Valuestore\Valuestore to support databases or cache:
      class DatabaseValuestore extends Valuestore {
          public function put($key, $value, $ttl = null) {
              DB::table('valuestore')->updateOrInsert(
                  ['key' => $key],
                  ['value' => $value, 'expires_at' => $ttl ? now()->addSeconds($ttl) : null]
              );
          }
          // Implement other methods...
      }
      
  2. Encryption:

    • Encrypt sensitive values before storing:
      use Illuminate\Support\Facades\Crypt;
      
      $valuestore->put('api.key', Crypt::encrypt($apiKey));
      $decrypted = Crypt::decrypt($valuestore->get('api.key'));
      
  3. Event Dispatching:

    • Trigger events on put/forget:
      Valuestore::put('key', 'value', now()->addHours(1));
      event(new ValueStored('key', 'value'));
      
  4. Validation Rules:

    • Add custom validation for keys/values:
      $validator = Validator::make(['key' => 'features.x'], [
          'key' => 'required|regex:/^features\.[a-z_]+$/i',
      ]);
      
  5. Fallback Mechanisms:

    • Combine with Laravel's cache for performance:
      $value = Cache::remember('valuestore:key', now()->addMinutes(5), function () {
          return Valuestore::get('key');
      });
      
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport