Weave 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.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support