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

Json Logic Php Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture Fit

  • Enhanced Rule Expressions: The new reduce feature with support for expression-based initial values (e.g., var-resolved contexts) expands use cases for:
    • Dynamic Aggregations: Compute running totals where the initial value depends on external data (e.g., reduce over an order’s items with an initial value tied to a user’s discount tier).
    • Context-Aware Logic: Simplify rules that previously required nested if/var combinations (e.g., "Start with the user’s balance, then reduce by each transaction").
    • Workflow State Machines: Model state transitions where the initial state is derived from context (e.g., reduce over approval steps with an initial state from var('current_status')).
  • Laravel Synergy:
    • Eloquent Collections: Integrates naturally with Laravel’s Collection::reduce() for database-agnostic aggregations.
    • Query Builder: Enable dynamic GROUP BY/HAVING logic via JSON rules (e.g., "Reduce by var('user_segment')").
  • Separation of Concerns: Reduces PHP-side logic for complex accumulations, keeping rule definitions in JSON.

Integration Feasibility

  • Backward Compatibility:
    • Non-Breaking: The change is additive and doesn’t alter existing reduce behavior (initial values can still be literals).
    • Laravel Collections: If using Collection::reduce(), ensure the package’s reduce operator aligns with Laravel’s method signature (e.g., (accumulator, current, index) => accumulator).
  • Database Integration:
    • Raw SQL: For PostgreSQL/MySQL, use JSON_EXTRACT or CAST to resolve var-based initial values in window functions (e.g., SUM(...) OVER (PARTITION BY var('category'))).
    • Eloquent: Add an accessor to hydrate reduce rules with context-aware initial values (e.g., Rule::resolveInitialValue($rule, $context)).
  • Testing:
    • Unit Tests: Validate edge cases like:
      • Circular var references in initial values (e.g., var('initial') where initial depends on itself).
      • Type mismatches (e.g., reducing numbers with a string initial value).
    • Integration Tests: Test with Laravel’s Collection and Query Builder to ensure operator parity.

Technical Risk

  • Performance:
    • Double Evaluation: Expression-based initial values may trigger two evaluations (once for the initial value, once for the reduce itself). Mitigate by:
      • Caching resolved initial values (e.g., Cache::remember("reduce_initial_{$contextHash}", ...)).
      • Using a single-pass evaluator if the package supports it.
    • Recursion: Deeply nested reduce + var chains could hit PHP’s recursion limit. Test with:
      ini_set('xdebug.max_nesting_level', 200); // For CI testing
      
  • Security:
    • Expression Injection: If initial values come from user input (e.g., var('user_input')), validate allowed expressions (e.g., whitelist var, +/- operators).
    • Denial of Service: Maliciously complex initial expressions (e.g., recursive var calls) could exhaust memory. Set a max evaluation depth.
  • Maintenance:
    • Package Maturity: No maintainer updates; fork if critical (e.g., add a JsonLogic\Evaluator::setMaxDepth()).
    • Documentation Gap: The release notes lack examples for Laravel-specific use cases (e.g., Eloquent reduce).

Key Questions

  1. Expression Resolution:
    • How will initial values be resolved? Will you use the package’s built-in var resolver or a custom Laravel context provider?
  2. Performance Trade-offs:
    • Is the double-evaluation overhead acceptable for your use case? If not, can you patch the package to optimize?
  3. Fallback Behavior:
    • What happens if resolving the initial value fails (e.g., var not found)? Default to 0? Throw an exception?
  4. Testing Coverage:
    • How will you test reduce with expression-based initial values in CI? Mock the context provider?
  5. Database Support:
    • Will you use this feature in raw SQL queries? If so, how will you handle var resolution in non-PHP contexts?
  6. Monitoring:
    • Will you track evaluation time for reduce operations to detect regressions?

Integration Approach

Stack Fit

  • Laravel Collections:
    • Wrapper Method: Extend Illuminate\Support\Collection with a jsonLogicReduce() method:
      public function jsonLogicReduce(string $rule, mixed $initialValue = null, callable $resolver = null): mixed
      {
          $evaluator = app(JsonLogicEvaluator::class);
          return $this->reduce(function ($carry, $item) use ($evaluator, $rule) {
              return $evaluator->evaluate($rule, ['item' => $item, 'carry' => $carry]);
          }, $resolver ? $resolver($initialValue) : $initialValue);
      }
      
    • Context Binding: Pass a context array to resolve var in initial values:
      $result = $collection->jsonLogicReduce(
          '{"reduce": ["var('item.price')", {"+": ["var('carry')", 1]}]}',
          ['initial' => 'var(user.discount)'],
          fn($val) => $evaluator->evaluate($val, ['user' => auth()->user()])
      );
      
  • Eloquent:
    • Accessors: Add a reduceRule accessor to models to hydrate rules with context:
      public function getReduceRuleAttribute($value)
      {
          return (new JsonLogicEvaluator)->evaluate(
              $value,
              ['initial' => $this->initialValueFromContext()]
          );
      }
      
  • Query Builder:
    • PostgreSQL: Use jsonb_path_query_first to resolve var in window functions:
      SELECT
        id,
        SUM(price) OVER (
          PARTITION BY category
        ) AS running_total
      FROM products
      WHERE category = jsonb_path_query_first('data->>category', '$')
      
    • MySQL: Use a JSON UDF or application-side filtering.

Migration Path

  1. Pilot with Simple reduce:
    • Start with literal initial values (e.g., {"reduce": [0, {"+": ["var('item')", 1]}]}).
    • Benchmark performance against native PHP array_reduce.
  2. Introduce Expressions:
    • Replace hardcoded initial values with var-resolved expressions (e.g., {"reduce": ["var('user.balance')", ...]}).
    • Use a feature flag to toggle the new syntax.
  3. Database Backing:
    • Add a rule_type column to your rules table to distinguish between old and new reduce syntax.
    • Write a data migration to convert legacy reduce rules to the new format.
  4. Cache Optimization:
    • Cache resolved initial values separately from compiled rules:
      Cache::remember(
          "reduce_initial_{$contextHash}",
          now()->addHours(1),
          fn() => $evaluator->evaluate($initialExpression, $context)
      );
      

Compatibility

  • PHP Version: No change; still requires PHP 8.1+.
  • Laravel Version: Test with Laravel 10.x+. For older versions, patch the package’s reduce operator to support named arguments.
  • Dependencies:
    • Conflict Risk: Low, but ensure no other package overrides array_reduce or Collection::reduce.
    • JSON Schema: Update validation rules to allow reduce with expression-based initial values.
  • Database:
    • PostgreSQL: Full support for JSON path queries.
    • MySQL: Limited; may require application-side filtering.

Sequencing

  1. Setup:
    • Install the package and update composer.json to pin to 1.5.1.
    • Add a service provider to bind the evaluator with a custom context resolver:
      $this->app->singleton(JsonLogicEvaluator::class, function ($app) {
          return new JsonLogicEvaluator(new ContextResolver($app['auth']));
      });
      
  2. Rule Definition:
    • Design a migration to add initial_expression to your rules table.
    • Seed with example rules using var-resolved initial values.
  3. Integration:
    • Replace the first reduce operation in your codebase with the new syntax.
    • Add caching for resolved initial values.
  4. Observability:
    • Log reduce evaluations with context hashes for debugging:
      Log::debug('Reduce evaluated', [
          'rule' => $rule,
          'initial_value' => $initialValue,
          'context_hash' => md5(json_encode($context)),
      
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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