phpdot / routing
High-performance segment-trie routing for PHP. PSR-7/15/17 compliant.
Requires
- php: >=8.5
- psr/container: ^2.0
- psr/http-factory: ^1.0
- psr/http-message: ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- phpdot/container: ^0.1
- phpdot/http: ^0.1
- phpstan/phpstan: ^2.0
- phpstan/phpstan-strict-rules: ^2.0
- phpunit/phpunit: ^13.0
README
High-performance HTTP routing built on a segment trie: routes compile into a prefix tree, so matching is
proportional to the request path's depth, not the number of routes. Fully PSR-7/15/17 — Router is a
PSR-15 RequestHandlerInterface with a middleware pipeline, typed route parameters, groups, and reverse
URL generation.
Table of Contents
Requirements
| Requirement | Constraint |
|---|---|
| PHP | >= 8.5 |
psr/container |
^2.0 |
psr/http-factory |
^1.0 |
psr/http-message |
^2.0 |
psr/http-server-handler |
^1.0 |
psr/http-server-middleware |
^1.0 |
phpdot/container is a dev-only suggestion — the #[Singleton] attribute on Router is inert until a
phpdot application reflects it.
Installation
composer require phpdot/routing
Usage
use PHPdot\Routing\Router; $router = new Router($container, $responseFactory); $router->get('/users', [UserController::class, 'index']); $router->get('/users/{id:int}', [UserController::class, 'show']); $router->post('/users', [UserController::class, 'store']); $response = $router->handle($request);
Route parameters can be typed ({id:int}), optional, or catch-all; handlers are [Controller::class, 'method'] arrays, Controller::class strings, or closures. Groups apply a shared prefix, name, and
middleware:
$router->group(['prefix' => '/admin'], function ($r) { $r->get('/dashboard', [DashboardController::class, 'index']); });
UrlGenerator builds URLs for named routes in reverse, and PSR-15 middleware runs as a pipeline around
the matched handler.
Architecture
Registered routes are compiled by RouteCompiler into segment sequences and inserted into a trie. On
each request TrieMatcher walks the trie by path segment, producing a RouteMatch (or a
MethodNotAllowed when the path exists under a different method). Router then runs the route's PSR-15
middleware pipeline and invokes the handler, resolving it through the container.
graph TD
REG["Route registration<br/><br/>get / post / group / name"]
COMPILER["RouteCompiler + PatternRegistry<br/><br/>pattern → segments"]
COLLECTION["RouteCollection → trie<br/><br/>TrieNode prefix tree"]
REQ["PSR-7 request → Router (PSR-15 handler)"]
MATCHER["TrieMatcher<br/><br/>walk by segment → RouteMatch / MethodNotAllowed"]
PIPE["Middleware pipeline → handler<br/><br/>resolved via the container"]
REG --> COMPILER
COMPILER --> COLLECTION
REQ --> MATCHER
COLLECTION --> MATCHER
MATCHER --> PIPE
Loading
Testing
composer install composer test # PHPUnit composer analyse # PHPStan, level max + strict rules composer cs-check # PHP-CS-Fixer composer check # All three
License
MIT.
This repository is a read-only mirror, generated by CI from phpdot/monorepo. Pull requests and issues belong in the monorepo.