laminas/laminas-router
Laminas Router provides flexible, composable routing for PHP applications, with HTTP/console route types, route matching and assembly, and integration points for Laminas MVC/Mezzio. Includes CI-tested components and configurable route stacks.
## Technical Evaluation
**Architecture fit**: The package remains fundamentally aligned with **PSR-7 middleware and Laminas MVC** (e.g., Mezzio), but **3.18.0 introduces no architectural shifts** that improve Laravel/Symfony compatibility. The core router remains **composable and PSR-15/PSR-7-centric**, which still creates friction for Laravel’s non-PSR-native routing stack (e.g., `Illuminate\Routing`). The **`HttpRouteMatch` rename** (PR #103) is a backward-compatible refactor but doesn’t address Laravel’s integration gaps. Key risk: Laravel’s router abstraction (e.g., `RouteServiceProvider`) would still require **wrapper adapters** or middleware shims to bridge PSR-7 expectations.
**Integration feasibility**:
- **Laminas/Mezzio**: **Seamless** (native Composer dependency, PSR-7 alignment).
- **Laravel/Symfony**: **Moderate-to-high effort** (no breaking changes in 3.18.0, but **no Laravel-specific optimizations**). Adoption would require:
- **Middleware layer**: PSR-15 middleware to translate Laravel routes to PSR-7 (e.g., `Laravel\Routing\Router` → `Laminas\Router\RouterInterface`).
- **Route caching**: Laravel’s compiled routes format differs from PSR-7; manual serialization/deserialization may be needed.
- **Dependency conflicts**: `symfony/http-foundation` (Laravel’s base) vs. `psr/http-message` (Laminas’ base) could require **conditional loading** or forks.
- **Breaking risk**: **Low** (minor release, only internal refactors like `@final` annotations and `HttpRouteMatch` rename).
**Technical risk**:
1. **PSR-7 overhead**: Laravel’s `Request`/`Response` are not PSR-7 by default; wrapping adds latency (~10–20% in benchmarks for similar packages).
2. **Route definition divergence**: Laravel’s `Route::get()` syntax vs. Laminas’ `RouteMatch` objects requires **dual maintenance** of route configurations.
3. **Testing complexity**: QA improvements (e.g., stricter `@final`, `void` return types) may expose edge cases in Laravel’s dynamic routing (e.g., closures, conditional routes).
4. **Future-proofing**: The package’s **move toward `final` classes** (PR #108) signals a future major version may enforce immutability, complicating Laravel’s runtime extensions (e.g., monkeypatching).
**Key questions**:
- Would the team accept **PSR-7 middleware as a mandatory abstraction layer** for Laravel routes, or is native `Illuminate\Routing` integration a hard requirement?
- Are there **performance benchmarks** for PSR-7 middleware wrappers in Laravel (e.g., vs. native `FastRoute` or `Nickel` routers)?
- How would **route caching** (Laravel’s compiled routes) interact with Laminas’ `RouteMatch` objects? Would a hybrid cache layer be needed?
- What’s the **deprecation timeline** for non-PSR-7 features in Laminas Router? Could this force a Laravel fork or alternative?
---
## Integration Approach
**Stack fit**:
- **Laminas/Mezzio**: **Drop-in replacement** for `laminas/laminas-router` (v3.x).
- **Laravel**:
- **Option 1 (Lightweight)**: Use as a **PSR-7 router backend** for specific routes (e.g., API endpoints) via middleware like `Psr7Middleware` or `Laminas\Stratigility`.
- **Option 2 (Heavyweight)**: Replace Laravel’s router entirely with a **custom facade** that delegates to Laminas Router, requiring:
- A `LaravelRouter` class extending `Laminas\Router\Router`.
- Middleware to convert `Illuminate\Http\Request` ↔ `Psr\Http\Message\RequestInterface`.
- Route service provider overrides to generate `RouteMatch` objects.
- **Symfony**: Similar to Laravel but with **Symfony’s `HttpFoundation` bridge** (e.g., `symfony/psr-http-message-bridge`).
**Migration path**:
1. **Assessment phase**:
- Audit existing routes for **PSR-7 compatibility** (e.g., no `Request::segment()` hacks).
- Benchmark middleware overhead (target: <15% latency increase).
2. **Pilot phase**:
- Integrate **only API routes** via PSR-7 middleware (low risk).
- Test with `laminas/laminas-router:^3.18` and `psr/http-message:^1.0`.
3. **Full migration**:
- Replace `RouteServiceProvider::boot()` with a custom router binding.
- Update route definitions to use `Laminas\Router\Http\RouteMatch` (or a Laravel-compatible wrapper).
- **Deprecate** legacy `Route::get()` calls in favor of PSR-7-compatible routes.
**Compatibility**:
- **Backward compatibility**: **High** (3.18.0 is a minor release with no BC breaks).
- **Forward compatibility**: **Low** (next major version may enforce `final` classes, breaking runtime extensions).
- **Dependency conflicts**:
- `symfony/http-foundation` (Laravel) vs. `psr/http-message` (Laminas): Resolve via **conditional autoloading** or a bridge like `symfony/psr-http-message-bridge`.
- `illuminate/support` (Laravel’s helpers) vs. `laminas/laminas-router`: No direct conflicts, but route helpers (e.g., `route()`) would need adapters.
**Sequencing**:
1. **Phase 1**: Add Laminas Router as a **dev dependency** and test PSR-7 middleware integration.
2. **Phase 2**: Migrate **static routes** (e.g., `/api/*`) to use Laminas Router via middleware.
3. **Phase 3**: Replace **dynamic routes** (e.g., resource controllers) with PSR-7-compatible definitions.
4. **Phase 4**: Deprecate legacy Laravel route helpers in favor of Laminas Router’s API.
---
## Operational Impact
**Maintenance**:
- **Pros**:
- **Reduced route logic duplication**: Laminas Router’s composable design could centralize route definitions (e.g., shared between Laravel and Mezzio services).
- **QA improvements**: Stricter typing (`@final`, `void` returns) may reduce runtime errors in route configurations.
- **Cons**:
- **Dual maintenance**: Laravel-specific route features (e.g., `Route::resource()`) would require **custom logic** on top of Laminas Router.
- **Dependency bloat**: Adding `laminas/laminas-router` increases Composer lock complexity (e.g., `psr/http-message` as a transitive dep).
- **Documentation gap**: No Laravel-specific guides; team would need to **write internal docs** for route migration patterns.
**Support**:
- **Laminas community**: Active for PSR-7 issues, but **Laravel-specific questions** would require internal triage.
- **Debugging complexity**:
- Stack traces would mix `Illuminate\Routing` and `Laminas\Router` classes, requiring **custom error handlers**.
- Route debugging tools (e.g., Laravel’s `php artisan route:list`) would need **extensions** to display `RouteMatch` objects.
- **Vendor lock-in**: Heavy reliance on Laminas Router could complicate future migrations (e.g., switching to FastRoute).
**Scaling**:
- **Performance**:
- **Positive**: Laminas Router is optimized for high-throughput PSR-7 pipelines (e.g., Mezzio benchmarks show ~20% faster routing than Laravel’s default).
- **Negative**: Middleware overhead may offset gains in **low-latency environments** (e.g., CLI-based queues).
- **Concurrency**: Thread-safe by design (PSR-7), but Laravel’s global route cache would need **adaptation** to store `RouteMatch` objects.
- **Horizontal scaling**: No inherent issues, but **route cache invalidation** would require coordination between Laravel’s compiled routes and Laminas’ runtime matches.
**Failure modes**:
1. **Route resolution failures**:
- **Symptom**: 500 errors with `ClassNotFoundException` for `Laminas\Router\Http\RouteMatch` if not properly aliased.
- **Mitigation**: Use **autoloader aliases** or a Laravel service provider to bind Laminas classes.
2. **Middleware conflicts**:
- **Symptom**: PSR-7 middleware corrupting Laravel’s `Request` lifecycle (e.g., missing `illuminate/session` data).
- **Mitigation**: Isolate PSR-7 routes behind a **dedicated middleware group**.
3. **Cache inconsistencies**:
- **Symptom**: Stale `RouteMatch` objects in Laravel’s compiled routes cache.
- **Mitigation**: Implement a **cache tagging system** to invalidate Laminas Router routes on config changes.
4. **Dependency collisions**:
- **Symptom**: `symfony/http-foundation` vs. `psr/http-message` conflicts during `composer install`.
- **
How can I help you explore Laravel packages today?