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

Expander Laravel Package

grasmash/expander

Expander is a Laravel package for managing feature rollouts and gating functionality. It helps you define “expansions” that can be enabled per environment, user, or percentage, making it easy to ship safely, run experiments, and toggle features without redeploys.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:
    composer require grasmash/expander
    
  2. Basic Usage:
    use Grasmash\Expander\Expander;
    
    $expander = new Expander();
    $config = [
        'database' => [
            'host' => 'localhost',
            'port' => 3306,
            'connection_string' => '${database.host}:${database.port}'
        ]
    ];
    $expanded = $expander->expandArrayProperties($config);
    
    First Use Case: Expand dot-notation references in Laravel config files (e.g., config/app.php) or API response templates.

Implementation Patterns

Core Workflows

  1. Config Expansion:

    • Use in config/app.php or config/services.php to reference other config values:
      'redis' => [
          'host' => '${cache.host}',
          'port' => '${cache.port}'
      ]
      
    • Load expanded config via config('redis.host').
  2. API Response Transformation:

    • Expand nested relationships in JSON:API responses:
      $response = [
          'data' => [
              'id' => '1',
              'type' => 'article',
              'attributes' => [
                  'title' => '${article.title}',
                  'author' => '${article.author.name}'
              ]
          ]
      ];
      $expander->expandArrayProperties($response);
      
  3. Dynamic Payload Processing:

    • Expand request payloads before validation/saving:
      $payload = $request->all();
      $expanded = $expander->expandArrayProperties($payload);
      

Laravel-Specific Patterns

  • Service Provider Integration:
    public function boot()
    {
        $this->app->singleton(Expander::class, fn() => new Expander());
    }
    
  • Command Bus/Jobs: Use Expander in jobs to resolve references before processing:
    public function handle()
    {
        $data = $this->expander->expandArrayProperties($this->data);
        // Process $data...
    }
    

Advanced Patterns

  • Custom Stringifiers: Override array-to-string conversion (e.g., for CSV):
    $expander->setStringifier(new class implements StringifierInterface {
        public function stringify(array $array): string {
            return implode('|', $array);
        }
    });
    
  • Environment Variables: Reference env vars directly:
    $config = ['log_level' => '${APP_LOG_LEVEL}'];
    putenv('APP_LOG_LEVEL=debug');
    $expanded = $expander->expandArrayProperties($config);
    

Gotchas and Tips

Pitfalls

  1. Unresolvable References:

    • Undefined ${not.real.property} remains unchanged. Use ?? for defaults:
      'fallback' => '${missing.key}??default_value'
      
    • Debug: Enable logging:
      $expander->setLogger(new \Monolog\Logger('expander'));
      
  2. Circular References:

    • Infinite loops if A references B and B references A. The package detects this but may not handle it gracefully. Solution: Validate input or use a DepthFirstExpander for controlled recursion.
  3. Type Mismatches:

    • Expanding ${array.key} into a non-array value breaks nested access. Tip: Validate structure before expansion.
  4. Environment Variables:

    • $_SERVER takes precedence over getenv(). Use putenv() for testing:
      putenv('TEST_VAR=value'); // Overrides $_SERVER
      

Debugging Tips

  • Verbose Output:
    $expander->expandArrayProperties($array, [], true); // Third arg = debug mode
    
  • Logger Integration:
    $expander->setLogger(new \Monolog\Handler\StreamHandler(storage_path('logs/expander.log')));
    

Performance

  • Avoid Over-Expansion: Expand only what’s needed (e.g., skip config('app.*') if unused).
  • Cache Expanders: For repeated expansions (e.g., API responses), cache the Expander instance or results:
    $this->app->singleton(Expander::class, fn() => new Expander());
    

Extension Points

  1. Custom Expanders: Extend Expander to add logic (e.g., for Laravel’s HasMany):

    class EloquentExpander extends Expander {
        public function expand($data) {
            if (is_array($data) && isset($data['model'])) {
                return $this->resolveEloquent($data['model']);
            }
            return parent::expand($data);
        }
    }
    
  2. Pre/Post-Processors: Use addExpander() to inject logic:

    $expander->addExpander('user', fn($id) => User::with('posts')->find($id));
    
  3. Validation: Combine with Laravel’s Validator to reject malformed references:

    $validator = Validator::make($array, ['key' => 'sometimes|expanded']);
    
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
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata