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

Math Eval Laravel Package

langleyfoxall/math_eval

Safely evaluate math expressions in PHP. langleyfoxall/math_eval parses and computes strings with operators, brackets, and common functions, ideal for user-defined formulas and configuration values without using eval(). Lightweight and easy to integrate in Laravel or any PHP app.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require langleyfoxall/math_eval
    

    Ensure your project uses PHP 8.0+ (HHVM is no longer supported).

  2. First Use Case: Evaluate a basic arithmetic expression in a Laravel controller or service:

    use MathEval\Evaluator;
    
    $result = (new Evaluator())->evaluate('2 + 3 * (4 - 1)');
    // Returns 11 (respects operator precedence)
    
  3. Where to Look First:

    • Documentation: Focus on the README for syntax rules (e.g., supported functions like sin(), log()).
    • Source Code: Explore Evaluator.php to understand parsing logic and safety mechanisms.
    • Tests: Review tests/ for edge cases (e.g., variable substitution, error handling).

Implementation Patterns

Usage Patterns

1. Basic Arithmetic

$evaluator = new Evaluator();
$result = $evaluator->evaluate('10 / 2 + 3'); // Returns 8

2. Variable Substitution

Pass an associative array for dynamic values:

$result = $evaluator->evaluate('a * b + c', [
    'a' => 5,
    'b' => 3,
    'c' => 2
]);
// Returns 17 (5*3 + 2)

3. Laravel Integration

Service Provider:

// app/Providers/AppServiceProvider.php
public function register()
{
    $this->app->singleton('math', function () {
        return new Evaluator();
    });
}

Facade (Optional):

// app/Facades/Math.php
namespace App\Facades;

use Illuminate\Support\Facades\Facade;

class Math extends Facade
{
    protected static function getFacadeAccessor() { return 'math'; }
}

Usage in Controllers:

$result = Math::evaluate('2 ** 3'); // Returns 8 (exponentiation)

4. Request Validation

Sanitize user input before evaluation (e.g., in Laravel Form Requests):

public function rules()
{
    return [
        'expression' => 'required|string|regex:/^[0-9+\-*\/%^().\s]+$/i',
    ];
}

5. Caching Frequent Expressions

Cache results for performance-critical paths:

$cacheKey = 'math:' . md5($expression);
$result = Cache::remember($cacheKey, now()->addHours(1), function () use ($evaluator, $expression) {
    return $evaluator->evaluate($expression);
});

6. Error Handling

Wrap evaluations in try-catch blocks:

try {
    $result = $evaluator->evaluate($userInput);
} catch (\MathEval\Exception\ParseError $e) {
    Log::error("Invalid expression: {$userInput}", ['error' => $e->getMessage()]);
    return response()->json(['error' => 'Invalid math expression'], 400);
}

Workflows

Dynamic Pricing Engine

  1. Store formulas in the database (e.g., discount_formula column).
  2. Evaluate at checkout:
    $formula = Product::find($id)->discount_formula;
    $discount = Math::evaluate($formula, [
        'price' => $cartTotal,
        'customer_tier' => $user->tier,
    ]);
    

Rule-Based Alerts

  1. Define thresholds in config:
    'alert_rules' => [
        'high_traffic' => '(visitors / avg_visitors) > 2',
    ],
    
  2. Evaluate in a scheduled job:
    $metrics = collect([...]);
    $rule = config('alert_rules.high_traffic');
    if (Math::evaluate($rule, $metrics->toArray())) {
        Alert::trigger('high_traffic');
    }
    

Data Transformation

  1. Apply formulas to Eloquent collections:
    $results = User::query()
        ->get()
        ->map(function ($user) {
            $user->score = Math::evaluate('(activity + reputation) / 2', [
                'activity' => $user->activity_score,
                'reputation' => $user->reputation,
            ]);
            return $user;
        });
    

Integration Tips

Extending Functionality

  1. Add Custom Functions: The package uses mossadal/math-parser. Extend by subclassing Evaluator:

    class CustomEvaluator extends Evaluator
    {
        protected function getFunctions()
        {
            return array_merge(parent::getFunctions(), [
                'custom_func' => function ($a, $b) {
                    return $a + $b * 2;
                },
            ]);
        }
    }
    
  2. Laravel Service Container Binding:

    $this->app->bind('math', function () {
        return new CustomEvaluator();
    });
    

Testing

  1. Unit Tests:

    public function testBasicArithmetic()
    {
        $evaluator = new Evaluator();
        $this->assertEquals(15, $evaluator->evaluate('3 * 5'));
    }
    
  2. Security Tests:

    public function testMaliciousInput()
    {
        $this->expectException(\MathEval\Exception\ParseError::class);
        $evaluator->evaluate('system("rm -rf")');
    }
    

Performance Optimization

  1. Precompile Expressions: For repeated use, parse expressions once and reuse:

    $parser = new \MathParser\Parser();
    $ast = $parser->parse('2 + 3 * x');
    $result = $evaluator->evaluateAST($ast, ['x' => 5]); // Returns 17
    
  2. Benchmark Alternatives: Compare with league/math or symfony/math for complex workloads.


Gotchas and Tips

Pitfalls

  1. No User-Defined Functions:

    • Issue: The package does not support custom functions added at runtime (only predefined ones like sin(), log()).
    • Workaround: Subclass Evaluator and override getFunctions() (see Extending Functionality above).
  2. Floating-Point Precision:

    • Issue: Results may have unexpected precision (e.g., 0.1 + 0.2 !== 0.3).
    • Workaround: Round results or use bcmath:
      $result = bcadd($evaluator->evaluate('0.1 + 0.2'), 0, 10);
      
  3. Recursive Expressions:

    • Issue: Expressions like x = x + 1 may cause infinite loops.
    • Workaround: Validate input to disallow recursive variables.
  4. Large Numbers:

    • Issue: May overflow for very large integers (e.g., 2^1000).
    • Workaround: Use gmp or bcmath:
      $result = gmp_strval(gmp_pow('2', 1000));
      
  5. HHVM Legacy Code:

    • Issue: If your codebase has HHVM-specific logic (e.g., type hints), ensure compatibility after removal.
    • Workaround: Test thoroughly on PHP 8.0+.
  6. No Error Context:

    • Issue: Exceptions lack details about which part of the expression failed.
    • Workaround: Log the full expression and use try-catch to capture errors.

Debugging

  1. Enable Debug Mode:

    $evaluator = new Evaluator();
    $evaluator->setDebug(true); // Logs parsing steps (if supported)
    
  2. Inspect AST (Abstract Syntax Tree):

    $parser = new \MathParser\Parser();
    $ast = $parser->parse('2 + 3 * x');
    dd($ast); // Debug the parsed structure
    
  3. Common Errors:

    • ParseError: Invalid syntax (e.g., unbalanced parentheses).
    • UndefinedVariable: Missing variable in substitution array.
    • **`DivisionByZero
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor