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

Options Bundle Laravel Package

damian972/options-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require damian972/options-bundle
    php artisan vendor:publish --provider="Damian972\OptionsBundle\OptionsBundle" --tag="config"
    
    • Publishes the options.yaml config file to config/packages/options.yaml.
  2. Database Migration Run the bundle’s migration to create the options table:

    php artisan migrate
    
    • The bundle provides a default migration under vendor/damian972/options-bundle/src/Resources/migrations/.
  3. First Use Case Inject the OptionsInterface into a controller/service and use it to store/retrieve values:

    use Damian972\OptionsBundle\Contracts\OptionsInterface;
    
    public function index(OptionsInterface $options) {
        $options->set(Option::make('site_name', 'MyApp'));
        $name = $options->get('site_name')?->getValue() ?? 'Default';
        return response()->json(['name' => $name]);
    }
    

Implementation Patterns

Core Workflows

  1. Storing Options

    • Use Option::make(key, value, parent) for basic storage.
    • Chain methods for customization (e.g., setName(), setDescription()).
    • Example:
      $options->set(Option::make('theme', 'dark')->setName('UI Theme'));
      
  2. Retrieving Options

    • Lazy Loading (Default): Query only when needed (config options.cache_all: false).
    • Eager Loading: Fetch all options once (set options.cache_all: true).
    • Parent-scoped retrieval:
      $globalTheme = $options->get('theme', 'global');
      
  3. Conditional Logic

    • Fallback values for missing keys:
      $timeout = $options->get('api_timeout')?->getValue() ?? 30;
      
  4. Bulk Operations

    • Use Option::make() in loops or factories to batch-insert options.

Integration Tips

  • Service Providers: Bind custom OptionsInterface implementations for testing:
    $this->app->bind(OptionsInterface::class, function () {
        return new MockOptionsService();
    });
    
  • Event Listeners: Extend the bundle by listening to OptionStored/OptionUpdated events (if supported).
  • Caching Layer: Combine with Laravel’s cache for performance:
    $value = Cache::remember("option_{$key}", now()->addHours(1), function () use ($options, $key) {
        return $options->get($key)?->getValue();
    });
    

Gotchas and Tips

Pitfalls

  1. Database Locking

    • Concurrent writes to the same key may cause race conditions. Use transactions for critical operations:
      DB::transaction(function () use ($options) {
          $options->set(Option::make('critical_setting', 'value'));
      });
      
  2. Parent Key Ambiguity

    • Retrieving without a parent (e.g., $options->get('key')) returns the first match. Always specify parents explicitly if multiple exist:
      // Avoid ambiguity
      $options->get('key', 'parent_scope');
      
  3. Lazy Loading Overhead

    • Disabling cache_all (default) triggers a query per get(). Enable cache_all in options.yaml for read-heavy apps:
      options:
          cache_all: true
      
  4. Migration Conflicts

    • If the options table already exists, the bundle’s migration may fail. Manually check the schema or disable migrations in config/packages/options.yaml:
      options:
          run_migrations: false
      

Debugging

  • Missing Options: Verify the options table exists and contains data:
    php artisan tinker
    >> \DB::table('options')->get();
    
  • Injection Issues: Ensure OptionsInterface is properly bound in the container. Check for typos in the service ID.

Extension Points

  1. Custom Option Classes Extend Option to add metadata (e.g., EncryptedOption):

    class EncryptedOption extends Option {
        public function getValue() {
            return decrypt(parent::getValue());
        }
    }
    
  2. Query Scoping Override the repository to filter options by scope (e.g., tenant ID):

    $options->get('key', 'tenant_123'); // Custom logic in repository
    
  3. Validation Add validation rules to Option via a trait or decorator:

    Option::make('email', 'test@example.com')->validate(fn ($value) => filter_var($value, FILTER_VALIDATE_EMAIL));
    
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.
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
splash/metadata
splash/openapi