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

Technical Evaluation

Architecture Fit

  • Strengths:

    • Aligns with Laravel’s data transformation and configuration-driven patterns (e.g., API responses, nested payloads, dynamic config).
    • Complements Laravel’s service layer and Eloquent by enabling declarative reference resolution (e.g., user.posts → hydrated relationships).
    • Supports modular design via custom expanders (e.g., UserExpander, ConfigExpander), reducing boilerplate in controllers/transformers.
    • Environment variable expansion (${env.VAR}) integrates with Laravel’s .env system, useful for dynamic configs (e.g., feature flags, API endpoints).
    • PSR-3 logging and custom stringifiers enable observability and formatting control, critical for debugging complex expansions.
  • Gaps:

    • No native Laravel service provider: Requires manual DI (e.g., binding Expander to Laravel’s container) or manual instantiation.
    • Limited Eloquent integration: While expanders can resolve models, the package doesn’t natively handle Eloquent relationships (e.g., with() clauses, lazy loading). This may force manual query logic in expanders.
    • No built-in caching: Recursive expansions could hit databases repeatedly. Laravel’s cache layer would need to be integrated manually.
    • Error handling: Undefined references (e.g., ${not.real.property}) default to leaving the placeholder intact. Custom error strategies (e.g., throw exceptions, use defaults) require wrapper logic.

Integration Feasibility

  • High for:
    • API payloads: Expanding request bodies (e.g., {"user": {"id": 1, "posts": ["expand"]}}) into hydrated objects.
    • Dynamic configs: Merging environment variables, database configs, or feature flags into runtime arrays.
    • Nested data structures: Resolving complex relationships (e.g., user.address.city.region) without recursive manual logic.
  • Medium for:
    • Eloquent-heavy apps: Requires custom expanders to bridge Laravel’s ORM (e.g., fn($id) => User::with('posts')->find($id)).
    • Performance-critical paths: No built-in optimizations for bulk expansions (e.g., batch queries).
  • Low for:
    • Real-time systems: Expansion is synchronous; async resolution would need custom implementation.
    • Flat data: Overkill for simple arrays without references.

Technical Risk

  • Critical:
    • Repository accessibility: The assessment-tpm.md mentions the repo is "inaccessible" (contradicted by GitHub link). Verify CI/CD, testing coverage, and community activity (e.g., open issues/PRs).
    • PHP 8.4 compatibility: While claimed, test edge cases (e.g., named args, union types) in Laravel’s context.
    • Circular references: No explicit safeguards (e.g., A -> B -> A). Custom logic or middleware (e.g., depth limits) may be needed.
  • Moderate:
    • Dependency conflicts: psr/log (v2+) may clash with Laravel’s logging stack (e.g., Monolog). Use NullLogger or Laravel’s Log facade.
    • Memory usage: Deeply nested expansions could exhaust stack/memory. Test with Laravel’s max_execution_time and memory_limit.
    • Type safety: Expanders return raw values (e.g., User model vs. array). Ensure consistent return types (e.g., fn($id): array).
  • Low:
    • MIT license: No legal/licensing risks.
    • Composer stability: Package is actively maintained (PHP 8.4 support, recent releases).

Key Questions

  1. Laravel-Specific Needs:
    • How will expanders interact with Laravel’s service container? Will we bind Expander globally or instantiate per-request?
    • Can expanders leverage Laravel’s caching (e.g., Cache::remember) or queue workers for async resolution?
    • How to handle Eloquent relationships? Will expanders duplicate with() logic or integrate with Laravel’s App\ExpandsMacro?
  2. Performance:
    • What’s the max depth/nesting level for expansions? Will we need to implement a recursion depth limit?
    • How to optimize bulk expansions (e.g., expanding an array of user IDs into full models)?
  3. Error Handling:
    • Should undefined references throw exceptions, return null, or use defaults? Example: ${env.MISSING_VAR}.
    • How to log expansion failures without leaking sensitive data (e.g., ${user.token})?
  4. Testing:
    • How to mock expanders in PHPUnit? Will we use Laravel’s Mockery or custom factories?
    • What’s the test coverage for edge cases (e.g., circular refs, non-string keys)?
  5. Alternatives:
    • Compare with Laravel’s @include/@includeWhen (Blade), collect() transformations, or API Resources.
    • Evaluate custom solutions (e.g., recursive array_walk) if the package lacks critical features.

Integration Approach

Stack Fit

  • Laravel Core:
    • Service Container: Bind Expander as a singleton or context-bound instance in AppServiceProvider:
      $this->app->singleton(Expander::class, fn($app) => new Expander($app['log']));
      
    • Request Pipeline: Use middleware to expand request payloads (e.g., ExpandRequestPayload).
    • API Resources: Integrate with Illuminate\Http\Resources\Json\JsonResource to expand nested fields:
      public function toArray($request) {
          return [
              'user' => Expander::expand($this->user->toArray(), ['user' => $this->user->load('posts')]),
          ];
      }
      
  • Eloquent:
    • Accessors/Mutators: Use expanders to compute dynamic attributes (e.g., full_name from first_name + last_name).
    • Scopes: Expand query parameters (e.g., where('status', ${request.status})).
  • Configuration:
    • Merge .env + DB configs: Expand config/app.php with environment variables:
      $config = Expander::expandArrayProperties(config('app'), $_ENV);
      

Migration Path

  1. Pilot Phase:
    • Start with non-critical paths (e.g., admin panels, config-driven features).
    • Replace manual array transformations (e.g., array_merge_recursive) with expandArrayProperties.
    • Example: Expand config/services.php to merge environment-specific overrides.
  2. Core Integration:
    • API Layer: Add expanders for User, Post, etc., in a dedicated ExpanderService.
    • Request Handling: Use middleware to expand incoming payloads (e.g., PATCH /posts with nested author references).
    • Caching: Wrap expanders in Laravel’s cache (e.g., Cache::remember('user:1', 10, fn() => User::find(1))).
  3. Full Adoption:
    • Replace custom transformation logic (e.g., in AppServiceProviders, FormRequests) with expanders.
    • Deprecate legacy transformation methods via Laravel’s deprecated() helper.

Compatibility

  • Laravel Versions:
    • Tested with PHP 8.4 → Compatible with Laravel 10+ (PHP 8.2+). For Laravel 9, pin to grasmash/expander:^2.0.
    • BC Breaks: PHP 5.4/5.5 dropped in v2.0; ensure no legacy code relies on old syntax.
  • Dependencies:
    • PSR-3 Logging: Use Laravel’s Log facade or NullLogger:
      $expander->setLogger(app(Log::class));
      
    • Stringifier: Default implode() may not suit all cases (e.g., JSON arrays). Extend StringifierInterface for custom formats.
  • Database:
    • Expanders can query databases, but avoid N+1 queries. Use Laravel’s with() or batch loading:
      $expander->addExpander('user', fn($id) => User::with('posts')->find($id));
      

Sequencing

  1. Phase 1: Configuration Expansion (Week 1):
    • Replace hardcoded configs with expandable arrays (e.g., config/expander.php).
    • Example: Merge config/app.php with .env overrides.
  2. Phase 2: API Payloads (Week 2):
    • Expand request bodies (e.g., PUT /users with nested address references).
    • Add middleware to validate expanded data (e.g., Validator::make($expandedPayload)).
  3. Phase 3: Eloquent Integration (Week 3):
    • Create expanders
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