PHPackages                             meraki/http-router - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. meraki/http-router

ActiveLibrary[HTTP &amp; Networking](/categories/http)

meraki/http-router
==================

Class-driven HTTP router for PHP 8.4+ — the action class name encodes intent (Collection / Item / Action), with no inflection, no route files, and pluggable casters for typed parameters.

0.8.0(3y ago)3318[5 issues](https://github.com/merakiframework/http-router/issues)MITPHPPHP ^8CI passing

Since Dec 30Pushed 2w ago1 watchersCompare

[ Source](https://github.com/merakiframework/http-router)[ Packagist](https://packagist.org/packages/meraki/http-router)[ RSS](/packages/meraki-http-router/feed)WikiDiscussions main Synced today

READMEChangelog (4)Dependencies (17)Versions (5)Used By (0)

http-router
===========

[](#http-router)

Maps HTTP requests to HTTP responses in PHP 8.4+.

Features
--------

[](#features)

**Routing model**

- Root path `/` mapping (configurable sub-namespace, default `Home`)
- RESTful route types from the class name alone — no inflection, no route files: `GetAllAction` (Collection), `GetOneAction` (Item), `GetAction` (Action / verb / static)
- Nested resources with parameter inheritance from the parent route (e.g. `/states/{state}/suburbs/{suburb}`)
- Disambiguation of static (`Action`) and RESTful routes at the same namespace — `/users/create` resolves to `Users\Create\GetAction`, not `Users\GetOneAction('create')`
- Variadic routing (trailing parameters absorbed by `...$args`)
- Configurable action prefix, suffix, and singular/plural indicators via `Router\Config`

**HTTP methods**

- `GET`, `POST`, `PUT`, `PATCH`, `DELETE` mapped from method-prefixed class names
- `HEAD` auto-derived from `GET` (body stripped at the SAPI layer)
- `OPTIONS` auto-synthesised (`204` + `Allow:`) listing every method available at the URL
- Additional methods (WebDAV, etc.) via `Config::withAdditionalMethods('propfind', …)`
- Allowed-methods list returned on `405`; method discovery is **poisoning-proof** (one misconfigured method doesn't hide the others)

**Parameters (via the `Caster` system)**

- Required, optional, and variadic parameters
- Built-in types: `string` (universal — never fails), `int`, `float`, `array` (CSV), enums (backed by value; pure enums by case name, case-insensitive), `UuidInterface` (requires `ramsey/uuid`)
- Union types (e.g. `int|string`) — first matching type wins; the universal `string` caster takes precedence in a union
- Value-object parameters (constructor-driven, arbitrary nesting — `Date(Year, Month, Day)` consumes one segment per leaf) — opt-in via `Config::withCaster(new ValueObjectCaster())`
- Custom parameter types: register your own `Caster` via `Config::withCaster()`

**Status semantics**

- `400` URL too short for a required parameter (or a value object's required ctor params)
- `404` no route of that shape (including too-many segments)
- `405` method not allowed, with `Allow:` populated
- `422` route matched but a value couldn't cast to its parameter's type
- `204` auto-synthesised `OPTIONS` response
- Misconfigured handler trees throw (`UnallowedVariadicParameter`, `SignatureMismatch`) instead of silently mis-routing — surface the developer error

**Extensibility**

- Custom PSR-3 logger via `Config::withLogger()`
- `Config` is immutable; all extension points are pluggable `Caster` implementations or `with*()` config methods

Roadmap
-------

[](#roadmap)

What's coming after alpha, grouped roughly by theme:

**Content negotiation** (planned for the negotiation milestone)

- Pluggable media-type / language negotiator
- `406 Not Acceptable` with the accepted types in the response

**Observability**

- Built-in logging hooks at route-resolution boundaries (the custom logger already plugs in via `Config::withLogger()`; the router doesn't emit log events yet)

**Performance**

- Optional route/reflection cache (route resolution today does `class_exists` per candidate + reflection per matched handler — a request-scoped cache is the obvious win)

**Routing extras**

- Prevent alternative root-path aliasing (so `/` and `/home` aren't both routable to `Home\GetAction`)
- Ignore non-URL handler parameters — e.g. let a handler typed `__invoke(Request $request, int $id)` skip `$request` for routing purposes and only consume `$id` from the URL

**Tooling**

- Reverse routing (build a URL from a handler class + arguments)
- Route dumper (enumerate every routable URL from the handler tree)
- Route-handler generator (scaffold a handler class for a given URL shape)

**Runtime**

- Concurrency support for Swoole (the router is stateless — likely already works, but needs verification + a documented setup)

Installation
------------

[](#installation)

```
composer install meraki/http-router

```

Usage
-----

[](#usage)

Instantiate the router, pass the request method and request target, then handle the result.

```
