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

Expression Language Laravel Package

symfony/expression-language

Symfony ExpressionLanguage provides an engine to compile and evaluate one-line expressions that return values (often booleans). Use it to embed simple, safe business rules and conditions in your app, with support for custom functions and variables.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Dynamic Logic Evaluation: Perfect fit for Laravel’s need to externalize business rules (e.g., policies, validation, feature flags) from code. The component’s compile-to-PHP approach avoids runtime parsing overhead, making it ideal for high-frequency evaluations (e.g., API middleware, looped policy checks).
  • Laravel Ecosystem Synergy: Aligns with Laravel’s service container, PSR standards, and Symfony component integration (e.g., used in Laravel’s own authorization package). Supports dependency injection and configuration-driven setups.
  • Security Model: Mitigates eval() risks by compiling expressions to static PHP and enforcing variable whitelisting. Critical for Laravel apps handling user-provided rules (e.g., admin panels) or sensitive logic (e.g., payments).
  • Performance: Cached compilation reduces evaluation latency for hot paths (e.g., API rate limiting, policy checks in loops). Benchmark against Laravel’s native if chains for critical workflows.

Integration Feasibility

  • Laravel Compatibility:
    • PHP 8.1+: Laravel 10/11 users are already compliant; older versions may require Symfony 6.x (PHP 7.4+).
    • Service Provider: Register the component as a Laravel service (e.g., ExpressionLanguageServiceProvider) to bind it to the container.
    • Facade/Package: Wrap the component in a Laravel package (e.g., laravel-expression-language) for consistency with other Symfony components (e.g., laravel-http-kernel).
  • Variable Providers: Requires defining custom providers to expose Laravel models/services (e.g., User, Request) to expressions. Example:
    $expressionLanguage->addProvider(new UserProvider());
    $expressionLanguage->addProvider(new RequestProvider());
    
  • Expression Syntax: Familiar to PHP/JavaScript devs (e.g., user.role === 'admin' || user.hasPermission('edit')), but may need documentation for Laravel-specific use cases (e.g., accessing request()->input()).

Technical Risk

  • Injection Vulnerabilities: High risk if expressions are evaluated with untrusted input. Mitigate by:
    • Whitelisting variables (e.g., only allow user, request, auth).
    • Validating expressions against a regex schema or AST analysis.
    • Pilot in low-risk areas (e.g., feature flags) before using in policies/validation.
  • Debugging Complexity: Stack traces for compiled expressions may obscure original logic. Solutions:
    • Log raw expressions before compilation.
    • Add a debug() method to dump parsed AST.
    • Use Laravel’s dd() with expression results.
  • Performance Overhead: Initial compilation adds latency. Optimize by:
    • Caching compiled expressions (e.g., Redis for shared instances).
    • Benchmarking against native PHP for critical paths.
  • Breaking Changes: Symfony 8.x enforces PHP 8.4+ and strict types. Laravel users must:
    • Upgrade PHP if using Symfony 8.x.
    • Test downgraded versions (e.g., Symfony 7.x for PHP 8.1) if needed.

Key Questions

  1. Use Cases:
    • Which Laravel features will prioritize this? (e.g., policies > validation > feature flags).
    • Are expressions static (cached) or dynamic (user-provided)?
  2. Security:
    • How will we validate expressions to prevent injection? (e.g., regex, AST, or manual review).
    • Who will have permissions to define rules? (e.g., admins via Nova, or developers only).
  3. Performance:
    • Which expressions are evaluated in hot paths (e.g., API middleware)?
    • Will we cache compiled expressions? If so, how? (e.g., Redis, file system).
  4. Adoption:
    • How will we train devs on the expression syntax and provider setup?
    • Will we create a Laravel package wrapper for easier adoption?
  5. Alternatives:
    • Have we compared this to custom parsers (e.g., Antlr) or existing tools (e.g., Laravel’s Gate + Policy)?
    • Is the maintenance burden justified for our scale? (e.g., 2K+ stars but no direct Laravel dependents).

Integration Approach

Stack Fit

  • Laravel Core: Integrates with:
    • Authorization: Replace if chains in Policy classes with expressions (e.g., auth()->user()->role === 'admin' && request()->path()->startsWith('/admin')).
    • Middleware: Dynamically route users based on expressions (e.g., user()->isPremium() && request()->is('api')).
    • Form Requests: Validate submissions with database-driven rules (e.g., "email || phone").
  • Symfony Ecosystem: Leverages:
    • Dependency Injection: Bind the component to Laravel’s container.
    • ExpressionLanguage Component: Reuse Symfony’s compiler, providers, and AST.
  • Database-Backed Rules: Store expressions in tables (e.g., permissions, feature_flags) and hydrate them at runtime:
    $rule = Rule::find($id);
    $expressionLanguage->evaluate($rule->expression, ['user' => auth()->user()]);
    

Migration Path

  1. Pilot Phase:
    • Feature Flags: Replace hardcoded if checks with expressions (e.g., user()->isBetaTester()).
    • Non-Critical Policies: Test in low-risk areas (e.g., non-sensitive data access).
  2. Core Integration:
    • Service Provider: Register the component:
      $this->app->singleton(ExpressionLanguage::class, function ($app) {
          $language = new ExpressionLanguage();
          $language->addProvider(new UserProvider());
          $language->addProvider(new RequestProvider());
          return $language;
      });
      
    • Facade: Create a Expression facade for convenience:
      use Illuminate\Support\Facades\Expression;
      
      if (Expression::evaluate('user()->isAdmin()')) { ... }
      
  3. Laravel Package (Optional):
    • Publish a laravel-expression-language package with:
      • Artisan commands for rule management.
      • Nova tools for admin interfaces.
      • Validation helpers (e.g., ExpressionValidator).
  4. Database Backing:
    • Add expression and variables columns to relevant tables (e.g., permissions, workflows).
    • Example schema:
      Schema::create('permissions', function (Blueprint $table) {
          $table->id();
          $table->string('name');
          $table->text('expression'); // e.g., "user.role === 'admin' && request()->is('admin/*')"
          $table->json('variables')->nullable(); // Whitelisted vars
      });
      

Compatibility

  • PHP Versions:
    • Symfony 8.x: Requires PHP 8.4+ (Laravel 11+).
    • Symfony 7.x: Requires PHP 8.1+ (Laravel 10).
    • Symfony 6.x: Requires PHP 7.4+ (Laravel 9).
  • Laravel Versions:
    • Laravel 10/11: Native compatibility with Symfony 7/8.
    • Laravel 9: Use Symfony 6.x (PHP 7.4+).
    • Legacy: Downgrade or polyfill missing features (e.g., null-safe operator ?.).
  • Dependencies:
    • Symfony Polyfill: Ensure compatibility with older PHP (e.g., symfony/polyfill-php80 for str_contains).
    • PSR-15 Middleware: Works with Laravel’s middleware stack.

Sequencing

  1. Phase 1: Foundation (2–4 weeks):
    • Set up the service provider and basic providers (e.g., User, Request).
    • Implement expression caching (e.g., Redis) for performance.
    • Write tests for core functionality (evaluation, compilation, error handling).
  2. Phase 2: Pilot Use Cases (3–6 weeks):
    • Feature Flags: Replace config('features.enabled') with dynamic expressions.
    • Non-Critical Policies: Test in a module with low risk (e.g., blog permissions).
  3. Phase 3: Core Integration (4–8 weeks):
    • Middleware: Dynamically route requests (e.g., ExpressionMiddleware).
    • Validation: Add ExpressionValidator to form requests.
    • Nova/Panel: Build admin interfaces for rule management.
  4. **
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
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
twbs/bootstrap4