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 a fast engine to evaluate or compile short expressions into PHP. Use it to compute values or boolean rules, with custom functions and variables, for dynamic logic in apps and components.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

Install via Composer:

composer require symfony/expression-language

First Use Case: Dynamic Feature Flags

  1. Define a Feature Flag Model:

    // app/Models/FeatureFlag.php
    use Illuminate\Database\Eloquent\Model;
    
    class FeatureFlag extends Model
    {
        protected $fillable = ['name', 'expression', 'enabled'];
    }
    
  2. Create a Service to Evaluate Flags:

    // app/Services/FeatureFlagEvaluator.php
    use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
    
    class FeatureFlagEvaluator
    {
        public function __construct(
            private ExpressionLanguage $expressionLanguage
        ) {}
    
        public function isEnabled(string $flagName, array $variables): bool
        {
            $flag = FeatureFlag::where('name', $flagName)->firstOrFail();
            return $flag->enabled &&
                   $this->expressionLanguage->evaluate(
                       $flag->expression,
                       $variables
                   );
        }
    }
    
  3. Register the Service in AppServiceProvider:

    public function register()
    {
        $this->app->singleton(FeatureFlagEvaluator::class, function ($app) {
            return new FeatureFlagEvaluator(new ExpressionLanguage());
        });
    }
    
  4. Use in a Controller:

    public function dashboard(Request $request, FeatureFlagEvaluator $evaluator)
    {
        $variables = [
            'user' => $request->user(),
            'request' => $request,
            'date' => new DateTime(),
        ];
    
        if ($evaluator->isEnabled('new_ui', $variables)) {
            return view('new_dashboard');
        }
        return view('old_dashboard');
    }
    
  5. Store an Expression in Database:

    INSERT INTO feature_flags (name, expression, enabled)
    VALUES ('new_ui', 'user.isBetaTester() && date.isWeekend()', true);
    

Key Files to Reference:


Implementation Patterns

Core Workflows

1. Variable Binding and Evaluation

  • Pattern: Pass variables as an associative array to evaluate().

    $expression = 'user.role === "admin" && order.total > 100';
    $variables = [
        'user' => $user,
        'order' => $order,
    ];
    $result = $expressionLanguage->evaluate($expression, $variables);
    
  • Laravel Integration: Bind common objects (e.g., Request, User) automatically:

    $expressionLanguage->addProvider(new Provider\LaravelProvider());
    $result = $expressionLanguage->evaluate('request.path() === "/admin"', [
        'request' => $request,
    ]);
    

2. Compiled Expressions (Performance)

  • Pattern: Compile once, evaluate many times (e.g., in loops or high-traffic endpoints).

    $compiled = $expressionLanguage->compile($expression);
    foreach ($orders as $order) {
        $result = $compiled->evaluate([
            'order' => $order,
            'user' => $user,
        ]);
    }
    
  • Caching: Cache compiled expressions in Laravel’s cache:

    $cacheKey = 'expr:'.$expression;
    $compiled = Cache::remember($cacheKey, 60, function () use ($expressionLanguage, $expression) {
        return $expressionLanguage->compile($expression);
    });
    

3. Dynamic Rule Storage

  • Pattern: Store expressions in a database and fetch them dynamically.

    $rule = Rule::where('name', 'discount_eligible')->first();
    $isEligible = $expressionLanguage->evaluate($rule->expression, [
        'user' => $user,
        'cart' => $cart,
    ]);
    
  • Laravel Eloquent Accessor:

    // app/Models/Rule.php
    public function getEvaluatedAttribute()
    {
        return app(ExpressionLanguage::class)->evaluate(
            $this->expression,
            $this->variables
        );
    }
    

4. Provider-Based Extensions

  • Pattern: Extend functionality with custom providers (e.g., for Laravel-specific helpers).

    // app/Providers/ExpressionLanguageServiceProvider.php
    use Symfony\Component\ExpressionLanguage\Provider\ProviderInterface;
    
    class LaravelProvider implements ProviderInterface
    {
        public function getFunctions()
        {
            return [
                'auth' => [$this, 'authFunction'],
                'route' => [$this, 'routeFunction'],
            ];
        }
    
        public function authFunction(array $arguments)
        {
            return auth()->check();
        }
    
        public function routeFunction(array $arguments)
        {
            return request()->route()->getName();
        }
    }
    
  • Register Provider:

    $expressionLanguage = new ExpressionLanguage();
    $expressionLanguage->addProvider(new LaravelProvider());
    

5. Policy Integration

  • Pattern: Replace if chains in policies with database-driven expressions.

    // app/Policies/UserPolicy.php
    public function update(User $user, User $model)
    {
        $expression = 'user.id === model.id || user.isAdmin()';
        return app(ExpressionLanguage::class)->evaluate($expression, [
            'user' => $user,
            'model' => $model,
        ]);
    }
    
  • Dynamic Policy Evaluation:

    $policyExpression = Policy::where('action', 'update')->where('model', 'User')->first();
    $allowed = $expressionLanguage->evaluate($policyExpression->expression, [
        'user' => $user,
        'model' => $model,
    ]);
    

6. Middleware for Dynamic Authorization

  • Pattern: Use expressions to gate middleware execution.
    // app/Http/Middleware/DynamicAuth.php
    public function handle(Request $request, Closure $next)
    {
        $expression = 'user.hasPermission("access_dashboard") && !request.isMobile()';
        if ($expressionLanguage->evaluate($expression, [
            'user' => $request->user(),
            'request' => $request,
        ])) {
            return $next($request);
        }
        abort(403);
    }
    

Integration Tips

Laravel-Specific Patterns

  1. Service Container Binding: Bind ExpressionLanguage as a singleton in AppServiceProvider:

    $this->app->singleton(ExpressionLanguage::class, function ($app) {
        $expressionLanguage = new ExpressionLanguage();
        $expressionLanguage->addProvider(new LaravelProvider());
        return $expressionLanguage;
    });
    
  2. Artisan Commands for Testing:

    // app/Console/Commands/TestExpression.php
    use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
    
    class TestExpression extends Command
    {
        protected $signature = 'expr:test {expression} {--variables=}';
        protected $description = 'Test an expression';
    
        public function handle(ExpressionLanguage $expressionLanguage)
        {
            $variables = json_decode($this->option('variables'), true) ?: [];
            $result = $expressionLanguage->evaluate(
                $this->argument('expression'),
                $variables
            );
            $this->info($result);
        }
    }
    
  3. Nova/Filament Integration:

    • Use expressions in Nova Toolbars or Filament Actions:
      // Nova Toolbar
      Toolbar::make()
          ->addField(
              new Button('Approve', 'btn-primary')
                  ->canSee(fn () => $expressionLanguage->evaluate(
                      'user.canApprove() && record.status === "pending"',
                      ['user' => $request->user(), 'record' => $resource]
                  ))
          );
      
  4. Event Listeners:

    // app/Listeners/EvaluateWorkflowRule.php
    public function handle(OrderApproved $event)
    {
        $expression = 'order.amount > 1000 && user.isPremium()';
        if ($expressionLanguage->evaluate($expression, [
            'order' => $event->order,
            'user' => $event->order->user,
        ])) {
            // Trigger premium workflow
        }
    }
    

Performance Optimization

  • Precompile Expressions: Cache compiled expressions in a compiled_expressions table with TTL.

    $compiled = Cache::remember("expr:{$expression}", 3600, function () use ($expressionLanguage, $expression) {
        return $expressionLanguage->compile($expression);
    });
    
  • Batch Evaluation: For bulk operations (e.g., updating records), compile once and reuse:

    $compiled = $expressionLanguage->compile('user.id === record.user_id && record.status === "pending"');
    foreach ($users as $user) {
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope