jwadhams/json-logic-php
Evaluate JsonLogic rules in PHP to share and store business logic across frontend and backend. Parses JSON-formatted logic (arrays/objects), supports nesting, comparisons, boolean ops, and data-driven evaluation via JsonLogic::apply with input data.
Installation
composer require jwadhams/json-logic-php:^1.5.1
No additional configuration is required—just require the package in your project.
First Use Case: Basic Rule Evaluation
use JsonLogic\JsonLogic;
$rule = [
'==', ['var', 'age'], 30
];
$data = ['age' => 30];
$result = JsonLogic::evaluate($rule, $data); // true
Where to Look First
JsonLogic::evaluate() for core functionality.JsonLogic::parse() for custom rule parsing (if needed).reduce (see Implementation Patterns).Dynamic Rule Evaluation
// Store rules in DB as JSON, fetch, and evaluate dynamically
$storedRule = json_decode($dbRule, true);
$result = JsonLogic::evaluate($storedRule, $userData);
Combining Rules with Operators
$complexRule = [
'all',
['==', ['var', 'status'], 'active'],
['>', ['var', 'score'], 50]
];
Variable Access
['var', 'key'] to reference nested data:
$rule = ['==', ['var', 'user.profile.role'], 'admin'];
Custom Functions
JsonLogic::addFunction():
JsonLogic::addFunction('customFn', function ($args, $data) {
return strtolower($args[0]);
});
$rule = ['customFn', ['var', 'name']];
Error Handling
try {
$result = JsonLogic::evaluate($rule, $data);
} catch (\JsonLogic\Exception\InvalidJsonLogic $e) {
Log::error("Invalid rule: " . $e->getMessage());
}
New in 1.5.1: Expression-Based reduce Initial Values
reduce operator now supports expression-based initial values evaluated in the outer context:
$rule = [
'reduce',
['var', 'numbers'], // iterable
['+', ['var', 'initial'], ['var', 'item']], // operation
['var', 'initial'] // initial value (now supports expressions)
];
$data = [
'numbers' => [1, 2, 3],
'initial' => 10
];
$result = JsonLogic::evaluate($rule, $data); // 16 (10 + 1 + 2 + 3)
['var', 'baseValue']).$this->app->singleton('jsonLogic', function () {
return new JsonLogic();
});
$validator = Validator::make($request->all(), [
'age' => ['required', function ($attribute, $value, $fail) {
$rule = ['>=', ['var', 'age'], 18];
if (!JsonLogic::evaluate($rule, ['age' => $value])) {
$fail('Must be at least 18.');
}
}]
]);
Variable Scope in reduce
reduce is now evaluated in the outer context, meaning ['var', 'key'] references the top-level $data array.$rule = [
'reduce',
['var', 'items'],
['+', ['var', 'total'], ['var', 'item']],
['var', 'total'] // Fails if 'total' is undefined in $data
];
$data = ['items' => [1, 2], 'total' => 0];
Type Mismatches
['==', 1, '1'] evaluate to false (strict comparison). Use ['==', ['var', 'id'], '1', true] for loose comparison (third argument enables type coercion).Circular References
['var', 'self'] where self references itself) may cause infinite loops.Performance
all/any operations) can be slow for large datasets.JsonLogic::setDebug(true); // Logs parsed rules to `storage/logs/json-logic.log`
JsonLogic::parse() to catch syntax errors early:
try {
JsonLogic::parse($rule);
} catch (\JsonLogic\Exception\InvalidJsonLogic $e) {
// Handle error
}
Custom Operators Extend core logic by adding new operators:
JsonLogic::addOperator('in_range', function ($args, $data) {
$value = $args[0][1] === 'var' ? $data[$args[0][0]] : $args[0];
return $value >= $args[1] && $value <= $args[2];
});
Usage:
$rule = ['in_range', ['var', 'age'], 18, 65];
Hooks for Pre/Post Evaluation
Override JsonLogic class methods (e.g., evaluate) in a decorator pattern for logging/auditing.
Serialization Serialize rules to JSON for storage/transmission:
$jsonRule = json_encode($rule);
$decodedRule = json_decode($jsonRule, true);
JsonLogic::evaluate() throws exceptions on invalid rules by default. Use JsonLogic::evaluate($rule, $data, false) to return null on errors instead.JsonLogic and modifying the resolveVar() method.reduce Expression Supportreduce operator now evaluates the initial value as an expression if it is a var or array. Ensure your rules account for this:
// Old behavior (if initial was a literal):
['reduce', ['var', 'items'], ['+', ['var', 'total'], ['var', 'item']], 0]
// New behavior (initial as expression):
['reduce', ['var', 'items'], ['+', ['var', 'total'], ['var', 'item']], ['var', 'total']]
reduce-based rules with the new release to confirm expected behavior.How can I help you explore Laravel packages today?