sebastian/recursion-context
sebastian/recursion-context is a small PHP utility for tracking recursive traversals and avoiding infinite loops when walking nested structures. It provides the RecursionContext class used by sebastian/comparator and PHPUnit to handle recursion safely.
sebastian/comparator and therefore PHPUnit; most Laravel teams already receive it transitively as a dev dependency. The product decision is not whether to adopt it, but whether to rely on it directly in our own test tooling — a much smaller commitment.8.x requires PHP 8.4+, 7.x supports PHP 8.3, 6.x supports PHP 8.2. Since PHPUnit's dependency chain will pull the major that matches our PHP floor, this package effectively becomes a canary for "which PHP minor is our test stack pinned to." That should feed directly into the roadmap item for PHP/Laravel runtime upgrades and the CI matrix.var_export-style output for failure diffs, custom PHPUnit constraints for deeply nested DTO/object graphs, debug panels that serialize request state, and assertion helpers for bidirectional Eloquent relationships. If we have a recurring "our test diffs hang or explode on circular models" complaint, this is the cheap fix.require-dev only. Adding it to production require is a red flag in code review and a signal that someone is doing deep variable traversal in app logic, which belongs in symfony/var-dumper or our own normalizers instead.Context.Adopt (directly, as --dev) when:
Look elsewhere when:
symfony/var-dumper, Laravel's own dd/dump plumbing, or explicit JsonSerializable/resource normalizers. This package is not designed for that and will create a runtime dependency on a test tool.spl_object_id(); arrays and scalars are handled by native recursion. If the data model is array-heavy, this doesn't solve the problem.To executives: No purchase, no license cost, no vendor negotiation — BSD-3, maintained by the author of PHPUnit, and already present in our dependency graph through the test suite. The only decision in front of us is timing: this library's current major requires PHP 8.4, so it's a concrete forcing function for the PHP upgrade already on the roadmap. Framing: a zero-cost reliability improvement for engineering, with one scheduling dependency attached.
To engineering leadership: Treat it as test infrastructure, not application architecture. It removes a class of flaky, hard-to-debug test failures caused by circular object graphs (common with bidirectional Eloquent relations and mocked DTOs) at the cost of one dev dependency we already have. Constraint to communicate clearly: dev-only, version-locked to our PHP floor, and the Context must be reset between independent operations — misuse produces phantom "recursion detected" results that will burn support time if undocumented.
To the engineering team: Use it behind a thin internal helper (safeExport(), a DeepEquals constraint) so we can swap it out if maintenance lapses. Don't call it from controllers, jobs, or anything that ships. Verify the PHP floor in CI before bumping the major, and pin majors deliberately rather than accepting whatever Composer resolves.
How can I help you explore Laravel packages today?