lukascivil/treewalker
TreeWalker is a lightweight PHP 8.1+ library for manipulating nested arrays, objects, and JSON strings interchangeably. It offers diffing, recursive walking with edits/deletion, merging, and dynamic key-path get/set/create operations, with configurable array, object, or JSON output.
Feature bets this unblocks
getdiff() gives you new / removed / edited buckets with oldvalue / newvalue, which is exactly the shape an "activity log" or "compare versions" UI needs. This is the single highest-value use case: it replaces a hand-rolled recursive diff (typically 3–5 days of engineering plus ongoing edge-case bugs) with a six-method dependency.getdiff() turns "why did this break?" into a readable, keyed diff. Good for support-facing internal consoles where polish matters more than RFC compliance.structMerge() (first-argument-wins) maps cleanly onto layered configuration: defaults < environment < tenant override. Useful for a "show effective config vs. baseline" screen.Build vs buy
composer require-installable, PHP 8.1+, and the entire public surface is six methods. Total replacement cost if it goes stale is roughly 1–3 engineer-days, which is a low enough ceiling to make adoption reversible — this is the key argument for a PM.Roadmap / scoping implications
getdiff() example output appears to label keys present only in the second structure as new while the shown values come from the first — the directionality is ambiguous or the docs are wrong. Before it lands in a customer-facing "what changed" view, someone must nail down the exact semantics with a spike and a conformance test. Budget half a day.Portfolio note
JsonDifference) from the same author. That's mildly attractive if the roadmap includes client-side previews of unsaved changes alongside the server-side diff — consistent semantics across tiers, one vendor relationship.Adopt when most of these are true
returntype switch (jsonstring | object | array) removes a whole class of serialization glue code from your feature.new/removed/edited shape is presentation-oriented and that's what you want.walker() passes parent, key, and value by reference) — e.g., redacting PII from a nested payload before logging, or pruning a nested response for a public API.getDynamicallyValue() / setDynamicallyValue() / createDynamicallyObjects() cover the "user maps a field to a.b.c in a settings screen" pattern without writing your own path parser.Look elsewhere when any of these are true
structMerge() is two-way with first-argument precedence only.Pre-adoption checklist (PM-owned gates)
getdiff() directionality and what debug / flat-slash-keys actually produce. Write down expected outputs as test fixtures.App\Support\JsonDiff) so the six methods are called from one place. That single decision reduces swap cost to hours.For executives
For engineering
getdiff, walker, structMerge, createDynamicallyObjects, getDynamicallyValue, setDynamicallyValue. All accept and return jsonstring | object | array interchangeably, controlled by a constructor flag — that alone removes serialization boilerplate.getdiff() example appears to invert the new vs. removed keys relative to the values shown. Treat the docs as suspect and lock behavior down with a conformance test suite in our repo. Also verify cycle handling and recursion depth on adversarial input — this code walks untrusted nested structures.How can I help you explore Laravel packages today?