laminas/laminas-router
Laminas Router is a flexible PHP routing component for matching HTTP and console requests to handlers and generating URLs from route definitions. It supports tree routing, route assembly, and integration with laminas-mvc and Mezzio.
Architecture fit — poor for a Laravel codebase. laminas-router is a routing component for Laminas MVC / Mezzio PSR-7 applications, not a routing system. It answers one question — "given this request, which named route and parameters match?" — and stops there. Laravel's Illuminate\Routing is not a swap-in component: it owns the dispatch pipeline, middleware groups and priority, route model binding, URL generation, signed URLs, subdomain/domain routing, route:cache compilation, and authorization hooks. There is no seam where laminas-router replaces it without forking the HTTP kernel. Feature coverage is a strict subset: literal, segment, regex, scheme, method, hostname, and tree-composed lookups. Laravel already does all of this plus the dispatch layer. Nothing here fills a Laravel capability gap.
Second impedance mismatch: message abstraction. The README states routing "works against the laminas-http request and responses," while Laravel is built on Symfony HttpFoundation. The package is mid-transition — laminas-http was moved to require-dev in 3.15, and a PSR-7-oriented HttpRouteInterface was introduced in 3.17 with the old Http\RouteInterface deprecated. So we would be adopting a component whose request contract is actively in flux, and would still need a PSR-7 ↔ HttpFoundation bridge in both directions.
Integration feasibility — technically installable, practically blocked. Composer coexistence is clean: BSD-3-Clause, PHP 8.2–8.5, no conflicting framework dependencies with current Laravel. But "installs" is not "integrates." There is no service provider, no config publishing, no facade, no Artisan commands, no route:list integration, and no participation in route:cache. The only viable placements are (a) a separate process/service, or (b) a shadow router gating a path prefix ahead of the Laravel kernel — both of which create a second source of truth for URLs.
Technical risk — low code risk, high integration and strategic risk. The library itself is well-tended for a small project: CI, Psalm, backward-compatibility checks, PHP-version currency, clear release notes. The risks are elsewhere:
RouteMatch → HttpRouteMatch, soft @final → final). Adopting now means absorbing a major-version migration on a component we do not control.url(), route(), and redirect generation will not know about these routes; signed URLs and email links will be wrong without an error.Key questions to resolve before any code is written:
HttpRouteInterface) stable enough to depend on, or does it need to land in v4.0 first?Stack fit — do not integrate into the Laravel request lifecycle. The idiomatic home for this package is Mezzio/Laminas MVC. If the underlying need is genuinely "PSR-7 routing in PHP," the correct move is a PSR-7 middleware stack (Mezzio, Slim) as a separate service, or Laravel plus a PSR-7 bridge — not grafting a foreign router into Illuminate\Routing. Recommend rejecting this package for the Laravel product surface and recording it as a watch item for legacy interoperability only.
Migration path — only meaningful for legacy absorption. If an acquired or inherited Laminas application must be folded into a Laravel platform, three options in ascending risk:
laminas-router, Laravel keeps Illuminate\Routing. Two deployables, one router each.Literal/Segment/Regex definitions into Laravel route files mechanically; the route grammar maps cleanly, but middleware, host constraints, and URL generation must be re-authored by hand.Compatibility constraints to document: PHP 8.2+ floor (8.1 dropped in 3.16, 8.5 added) — fine for current Laravel, a blocker for any pinned 8.0/8.1 service. laminas-http is no longer a hard dependency, so any existing code calling match() with a Laminas\Http\Request needs the PSR-7 path instead. No Laravel-aware tooling: no route cache, no route listing, no middleware awareness.
Sequencing (gated, each step may kill the initiative):
composer require in a scratch project; exercise match() standalone against representative paths, hosts, schemes, and methods. No framework coupling.laminas-router → back, including a 404 and a parameterized route. Measure latency overhead per request.Maintenance. Single-vendor, volunteer-maintained, with a narrow contributor pool (recent releases credit one to three people, predominantly the same two maintainers). Release cadence is healthy and PHP-version support is current, but the bus factor is small and there is no commercial backer. We must add Laminas advisories to our vulnerability feed — our existing Laravel/Symfony monitoring will not cover it.
Support. Community only: GitHub issues, Laminas chat, Discourse forum. No SLA, no escalation path, no vendor to call during an incident. For a component on the critical request path, that is a material gap versus Laravel's commercial ecosystem (Forge, Vapor, partners, first-party security releases).
Scaling. Routing itself is not a scaling concern — the tree-structured lookup is a fast b-tree walk and will not be the bottleneck at any traffic level we operate. The scaling cost is operational: two route caches to warm on deploy, two debugging surfaces during incidents, and doubled configuration drift risk when paths change on one side and not the other.
Failure modes to instrument for:
auth, throttle, verified) does not run. This is a security incident, not a bug.url(), route(), redirects, password-reset links, and signed URLs silently ignore these routes.route:cache — Laravel's cache will not know about foreign routes; deploy ordering matters.final enforcement land in a major we do not schedule.laminas-http removal — any call site passing a Laminas HTTP request fails at runtime, not at install time.Ramp-up. Engineers must learn Laminas idioms — plugin managers, RouteStackInterface trees, Literal/Segment/Regex route classes, and the new HttpRouteInterface semantics. This knowledge is non-transferable to the rest of our Laravel portfolio and thinly represented in the hiring market, and there is no equivalent of route:list for debugging these routes. Budget a week of unfamiliarity per engineer, plus permanent context in every on-call runbook.
Recommendation. Reject for the Laravel product surface. The package is competently maintained and the high opportunity score reflects whitespace in the Laminas ecosystem, not an opening for a Laravel platform. Retain on the watch list solely as a dependency of legacy Laminas applications we may acquire, and if such an acquisition occurs, default to an edge-proxy split over in-kernel integration.
How can I help you explore Laravel packages today?