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

String Calc Laravel Package

chriskonnertz/string-calc

StringCalc is a lightweight PHP library that evaluates mathematical expressions passed as strings, turning terms like 1+1 or sqrt(16)*2 into results. It supports basic operators, brackets, and common functions, with no dependencies—ideal for calculators and formula inputs.

Deep Wiki
Context7

Getting Started

Install with Composer:

composer require chriskonnertz/string-calc

The smallest useful integration is the StringCalc facade:

use ChrisKonnertz\StringCalc\StringCalc;

$calc = new StringCalc();

echo $calc->calculate('(2 + 3) * 4 / 2'); // 10
echo $calc->calculate('sqrt(16) + pow(2, 3)'); // 12

Where to look first:

  1. README.md for the supported operators, functions, and constants (pi, e, sin, cos, sqrt, log, etc.).
  2. src/StringCalc.php — the facade that wires the tokenizer, parser, and calculator together.
  3. src/Symbols/Concrete — the actual operator, function, and constant implementations. This is the best reference when you need to add your own.
  4. src/Exceptions — the failure modes you will need to catch at your application boundary.

The first real use case is almost always replacing eval() in a feature where an admin, customer, or configuration author types a formula: pricing rules, discount expressions, margin calculations, dynamic form fields, or spreadsheet-style inputs. StringCalc gives you arithmetic parsing without the arbitrary-code-execution risk of eval().

Implementation Patterns

Wrap it in one application service. Construct StringCalc once per request (or register it as a singleton in the container) and inject a small wrapper rather than scattering new StringCalc() through controllers:

final class FormulaEvaluator
{
    public function __construct(private StringCalc $calc = new StringCalc()) {}

    public function evaluate(string $expression): float
    {
        return (float) $this->calc->calculate($expression);
    }
}

Validate before you calculate. Treat the expression as untrusted input: enforce a maximum length, reject unexpected characters, and keep the grammar to what the package supports. This protects you from accidental pathological input and gives users a better message than a parser exception.

Map library exceptions to domain errors. Catch \Throwable at the boundary, then narrow to the library’s exception classes under ChrisKonnertz\StringCalc\Exceptions. Return a validation error (“The formula is not valid”) rather than leaking parser internals.

Substitute variables yourself. The package evaluates literal expressions; it is not a variable-binding formula engine. For templates like price * quantity or {price} * {qty}, replace placeholders with numeric literals before calling calculate(). Validate each substituted value is numeric, and use a strict placeholder syntax so user text cannot smuggle in operators.

$expression = strtr($template, [
    '{price}' => (string) $price,
    '{qty}'   => (string) $quantity,
]);

$result = $evaluator->evaluate($expression);

Add custom symbols when the built-in set is insufficient. Extend the abstract operator/function/constant classes in src/Symbols, set the identifier and arity, and implement the execution method. Register the symbol on the container before the first calculation:

$calc->getContainer()->getSymbols()->add(new MyCustomFunction());

Check the corresponding Abstract* class for the exact property and method signatures; they are the contract.

Round at the boundary, not inside the math. Keep full precision while composing expressions, then apply round() or a money formatter only when presenting the result.

Test with a data provider. A table of valid expressions and expected outputs, plus a table of invalid expressions and expected exception types, catches most regressions and documents the supported grammar for your team.

Cache repeated evaluations. If the same static formula is evaluated many times (for example, a stored pricing rule), cache by expression string plus substituted inputs. There is no compiled-expression API, so caching the evaluated result is the practical optimization.

Gotchas and Tips

  • % is modulo, not percentage. If users type 10%, they probably mean 0.10. Handle percentage semantics in your UI or preprocessor; do not assume the parser does it.
  • Trigonometry uses radians. If your users think in degrees, convert before evaluation or register degree-based helper functions.
  • Implicit multiplication may not parse. Write 2 * (3 + 4), not 2(3 + 4), and normalize user input if you want to accept the latter.
  • Locale decimal separators are not handled for you. 1,5 + 2 is not 1.5 + 2. Normalize commas to dots only when you are certain the comma is a decimal separator and not a function argument separator.
  • Floating-point results surprise users. 0.1 + 0.2 produces 0.30000000000000004. Round before display and compare with an epsilon in tests.
  • Domain errors need checking. Division by zero, sqrt(-1), and log(0) may throw or produce non-finite values depending on the operation. Validate inputs and check results with is_finite().
  • Guard against expensive input. Deeply nested parentheses or extremely long expressions can be slow. Cap expression length and nesting depth at the application layer.
  • Respect operator precedence and unary minus. Expressions like -2^2 and 2 * -3 are common sources of disagreement between what a user expects and what the grammar defines. Test these explicitly.
  • Custom symbol identifiers must not collide. Adding a function named like an existing one, or changing the symbol set after calculations have started, can produce confusing behavior. Register symbols once at construction time.
  • Container mutation is per instance. Do not share one mutated StringCalc instance across tenants with different custom symbols; construct per configuration.
  • Maintenance risk. The last release was May 2022. Run it against your target PHP version in CI (especially PHP 8.2/8.3) and watch for deprecation notices before committing to it for long-lived code.
  • It is a calculator, not a formula language. There are no variables, conditionals, string functions, or cell references. If your requirements grow beyond arithmetic, plan for a different expression engine rather than stretching this one.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings