leongrdic/smplang
SMPLang is a small PHP language/parser package for defining and evaluating simple expressions in your app. Useful for lightweight DSLs, rules, filters, or templating-like syntax, with an emphasis on minimal setup and easy integration into Laravel projects.
Installation:
composer require leongrdic/smplang
Requires PHP 8.0+.
First Use Case: Evaluate a simple expression:
use Leongrdic\Smplang\Smplang;
$smplang = new Smplang();
$result = $smplang->evaluate('2 + 3 * 4'); // Returns 14
Where to Look First:
Expression Evaluation:
$smplang = new Smplang();
$result = $smplang->evaluate('(5 + 3) * 2'); // 16
+, -, *, /, %), parentheses, and basic functions.Variable Binding:
$smplang = new Smplang();
$smplang->bind('x', 10);
$result = $smplang->evaluate('x * 2'); // 20
Object/Method Integration:
class Calculator {
public function add($a, $b) { return $a + $b; }
}
$smplang = new Smplang();
$smplang->bind('calc', new Calculator());
$result = $smplang->evaluate('calc.add(5, 3)'); // 8
Dynamic Contexts:
$smplang = new Smplang();
$context = ['user' => ['name' => 'Alice']];
$result = $smplang->evaluate('user.name', $context); // 'Alice'
Laravel Blade Integration:
Create a custom directive to embed smplang expressions:
Blade::directive('eval', function ($expression) {
return "<?php echo app(Leongrdic\Smplang\Smplang::class)->evaluate($expression); ?>";
});
Usage in Blade:
@eval('2 + 3')
Form Validation:
Dynamically validate inputs using smplang expressions:
$validator = Validator::make($request->all(), [
'age' => ['required', function ($attribute, $value, $fail) {
$smplang = new Smplang();
if (!$smplang->evaluate("{$value} >= 18")) {
$fail('Must be 18+.');
}
}]
]);
API Response Filtering: Filter API responses dynamically:
$response = collect($users)
->filter(function ($user) use ($smplang) {
return $smplang->evaluate("{$user['role']} === 'admin'");
});
No eval() Equivalent:
smplang is not a full PHP replacement. Avoid complex logic (loops, conditionals beyond basic arithmetic).smplang for expressions.
// ❌ Avoid:
$smplang->evaluate('if (x > 0) { return x; } else { return -x; }');
// ✅ Do:
$result = $smplang->evaluate('x') > 0 ? $smplang->evaluate('x') : -$smplang->evaluate('x');
Object Property Access:
__get and the property doesn’t exist (pre-1.0.1). Now throws Smplang\Exception.try-catch:
try {
$result = $smplang->evaluate('user.nonexistent');
} catch (\Leongrdic\Smplang\Exception $e) {
report($e); // Log or handle gracefully
}
Method Overloading:
__call magic methods are supported, but argument passing is strict (no variadic support).$obj = new class {
public function __call($name, $args) {
return "Called {$name} with " . implode(', ', $args);
}
};
$smplang->bind('obj', $obj);
$smplang->evaluate('obj.unknown(1, 2)'); // "Called unknown with 1, 2"
Performance:
Smplang::compile() for one-time evaluations:
$compiled = $smplang->compile('2 + 3');
$result = $compiled(); // Faster than evaluate()
Enable Verbose Errors:
Set the debug flag in the constructor:
$smplang = new Smplang(['debug' => true]);
Throws detailed exceptions for syntax errors.
Log Expressions: Use Laravel’s logging to track evaluated expressions:
$smplang->evaluate('user.score > 100', ['user' => ['score' => 150]]);
\Log::debug('Evaluated: user.score > 100', ['result' => true]);
Custom Functions:
Register global functions via Smplang::registerFunction():
$smplang->registerFunction('max', function ($a, $b) {
return max($a, $b);
});
$smplang->evaluate('max(1, 5)'); // 5
Context Overrides:
Override default context behavior by extending Smplang:
class CustomSmplang extends Smplang {
protected function resolveVariable($name, $context) {
if ($name === 'default_value') {
return 'custom_default';
}
return parent::resolveVariable($name, $context);
}
}
Syntax Extensions:
$expression = str_replace('^', '**', $rawInput); // Replace ^ with ** for exponentiation
$result = $smplang->evaluate($expression);
Smplang instance is stateless between evaluations. Rebind variables as needed:
$smplang = new Smplang();
$smplang->bind('x', 1); // Reset x for each evaluation
How can I help you explore Laravel packages today?