PHPackages                             zero-to-prod/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. zero-to-prod/http-router

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

zero-to-prod/http-router
========================

High-performance HTTP router for PHP with three-level indexing, PSR-15 middleware support, and route caching

v0.1.2(5mo ago)0406MITPHPPHP &gt;=7.2CI passing

Since Dec 9Pushed 4mo agoCompare

[ Source](https://github.com/zero-to-prod/http-router)[ Packagist](https://packagist.org/packages/zero-to-prod/http-router)[ Docs](https://github.com/zero-to-prod/http-router)[ Fund](https://github.com/sponsors/zero-to-prod)[ RSS](/packages/zero-to-prod-http-router/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (6)Versions (2)Used By (0)

HTTP Router
===========

[](#http-router)

[![Repo](https://camo.githubusercontent.com/9a90a3efeee26aed7d7f2feee9cd84566a26f9c362cc773b184d076210906e1c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6769746875622d677261793f6c6f676f3d676974687562)](https://github.com/zero-to-prod/http-router)[![GitHub Actions Workflow Status](https://camo.githubusercontent.com/a7958e54c166f99f019b1fde8d44e90bde508e56ec9118c314bc46ca0ff43941/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7a65726f2d746f2d70726f642f687474702d726f757465722f746573742e796d6c3f6c6162656c3d74657374)](https://github.com/zero-to-prod/http-router/actions)[![Packagist Downloads](https://camo.githubusercontent.com/10057efa551ee30d82e80a1ec05a8b4d5b95f34a31769671276261fccb35ff06/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7a65726f2d746f2d70726f642f687474702d726f75746572)](https://packagist.org/packages/zero-to-prod/http-router)[![php](https://camo.githubusercontent.com/db6d1ce1d749f8bb33a3a7fc297192569c88069989c09e3a1557c95d88e6e43b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f7a65726f2d746f2d70726f642f687474702d726f757465722e7376673f636f6c6f723d707572706c65)](https://packagist.org/packages/zero-to-prod/http-router/stats)[![Packagist Version](https://camo.githubusercontent.com/e42ca53e8e27e33b64e6b463112463f044cb31f1c1d24a1eff3d9c63601da1a4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7a65726f2d746f2d70726f642f687474702d726f75746572)](https://packagist.org/packages/zero-to-prod/http-router)[![License](https://camo.githubusercontent.com/b25476a2741f52b2c84d2c63c314a7ed3b6e114ac6ced8436a998ea25a5ff9bd/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7a65726f2d746f2d70726f642f687474702d726f75746572)](https://github.com/zero-to-prod/http-router)

High-performance HTTP router for PHP 7.2+ with three-level indexing, PSR-15 middleware support, and route caching.

Features
--------

[](#features)

- **High Performance**: Three-level route indexing for O(1) static route lookup and optimized dynamic route matching
- **PSR-15 Middleware**: Full support for PSR-15 middleware alongside legacy variadic middleware
- **Route Caching**: Production-optimized serialization with automatic cache management
- **RESTful Resources**: Automatic generation of resourceful routes
- **Route Groups**: Organize routes with shared prefixes and middleware
- **Named Routes**: Generate URLs from route names with parameter substitution
- **Parameter Constraints**: Inline (`{id:\d+}`) and fluent (`where()`) constraint syntax
- **PHP 7.1+ Compatible**: Broad multi-version support

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

[](#installation)

```
composer require zero-to-prod/http-router
```

Quick Start
-----------

[](#quick-start)

```
use Zerotoprod\HttpRouter\HttpRouter;

$router = HttpRouter::for($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);

$router->get('/users/{id}', [UserController::class, 'show'])
    ->where('id', '\d+')
    ->name('user.show')
    ->middleware(AuthMiddleware::class);

$router->dispatch();
```

Basic Usage
-----------

[](#basic-usage)

### Defining Routes

[](#defining-routes)

```
use Zerotoprod\HttpRouter\HttpRouter;

// Create router and define routes
$router = HttpRouter::create();

// Static routes
$router->get('/', function() {
    echo 'Home';
});

// Dynamic routes with parameters
$router->get('/users/{id}', function(array $params) {
    echo "User ID: " . $params['id'];
});

// Routes with inline constraints
$router->get('/posts/{id:\d+}', [PostController::class, 'show']);

// Routes with fluent constraints
$router->get('/users/{id}', [UserController::class, 'show'])
    ->where('id', '\d+');

// IMPORTANT: Set the request method and URI before dispatching
$router->forRequest($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
$router->dispatch();
```

**Alternative Shorthand:**

```
// Combine create() and forRequest() in one call
$router = HttpRouter::for($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);

$router->get('/', function() {
    echo 'Home';
});

$router->dispatch();
```

### HTTP Methods

[](#http-methods)

```
$router->get('/users', [UserController::class, 'index']);
$router->post('/users', [UserController::class, 'store']);
$router->put('/users/{id}', [UserController::class, 'update']);
$router->patch('/users/{id}', [UserController::class, 'patch']);
$router->delete('/users/{id}', [UserController::class, 'destroy']);
$router->options('/users', [UserController::class, 'options']);
$router->head('/users', [UserController::class, 'head']);

// Multiple methods
$router->any('/users/{id}', [UserController::class, 'handler'], ['GET', 'POST']);
```

### RESTful Resources

[](#restful-resources)

```
// Generates all 7 RESTful routes
$router->resource('users', UserController::class);

// With filters
$router->resource('posts', PostController::class, ['only' => ['index', 'show']]);
$router->resource('comments', CommentController::class, ['except' => ['destroy']]);
```

Generated routes:

- `GET /users` → `index()`
- `GET /users/create` → `create()`
- `POST /users` → `store()`
- `GET /users/{id}` → `show()`
- `GET /users/{id}/edit` → `edit()`
- `PUT /users/{id}` → `update()`
- `DELETE /users/{id}` → `destroy()`

### Route Groups

[](#route-groups)

```
// Prefix groups
$router->prefix('api/v1')->group(function($router) {
    $router->get('/users', [UserController::class, 'index']); // /api/v1/users
});

// Middleware groups
$router->middleware([AuthMiddleware::class])->group(function($router) {
    $router->get('/dashboard', [DashboardController::class, 'index']);
});

// Combined
$router->prefix('admin')
    ->middleware([AuthMiddleware::class, AdminMiddleware::class])
    ->group(function($router) {
        $router->get('/users', [AdminController::class, 'users']);
    });
```

### Named Routes

[](#named-routes)

```
// Define named route
$router->get('/users/{id}', [UserController::class, 'show'])
    ->name('user.show');

// Generate URL
$url = $router->route('user.show', ['id' => 123]); // /users/123
```

### Middleware

[](#middleware)

#### PSR-15 Middleware

[](#psr-15-middleware)

```
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AuthMiddleware implements MiddlewareInterface
{
    public function process(
        ServerRequestInterface $request,
        RequestHandlerInterface $handler
    ): ResponseInterface {
        // Check authentication
        return $handler->handle($request);
    }
}

$router->get('/dashboard', [DashboardController::class, 'index'])
    ->middleware(AuthMiddleware::class);
```

#### Variadic Middleware

[](#variadic-middleware)

```
class LogMiddleware
{
    public function __invoke(callable $next, ...$context)
    {
        // Before request
        error_log('Request started');

        $next();

        // After request
        error_log('Request completed');
    }
}

$router->get('/users', [UserController::class, 'index'])
    ->middleware(LogMiddleware::class);
```

#### Global Middleware

[](#global-middleware)

```
$router->globalMiddleware([
    CorsMiddleware::class,
    SecurityHeadersMiddleware::class
]);
```

### Route Caching

[](#route-caching)

```
// Enable automatic caching in production
$router->autoCache(
    cache_path: __DIR__ . '/cache/routes.php',
    env_var: 'APP_ENV',
    cache_envs: ['production']
);

// Manual caching
if ($router->isCacheable()) {
    $compiled = $router->compile();
    file_put_contents('routes.php', $compiled);
}

// Load from cache
$data = file_get_contents('routes.php');
$router->loadCompiled($data);
```

### Fallback Handler

[](#fallback-handler)

```
$router->fallback(function() {
    http_response_code(404);
    echo 'Not Found';
});
```

Advanced Usage
--------------

[](#advanced-usage)

### Dispatching with Context

[](#dispatching-with-context)

```
// Pass additional arguments to actions and middleware
$router = Router::for('GET', '/users', $container, $request);
$router->get('/users', function(array $params, $container, $request) {
    // Access container and request
});
```

### Optional Parameters

[](#optional-parameters)

```
$router->get('/users/{id?}', function(array $params) {
    $id = $params['id'] ?? 'all';
    echo "User: $id";
});
```

### Multiple Constraints

[](#multiple-constraints)

```
$router->get('/posts/{year}/{month}/{slug}', [PostController::class, 'show'])
    ->where([
        'year' => '\d{4}',
        'month' => '\d{2}',
        'slug' => '[a-z0-9-]+'
    ]);
```

### Wildcard Routes

[](#wildcard-routes)

```
// Match everything including slashes
$router->get('/search/{query}', [SearchController::class, 'search'])
    ->where('query', '.*');
```

Action Types
------------

[](#action-types)

The router supports three types of actions:

### Controller Array

[](#controller-array)

```
$router->get('/users', [UserController::class, 'index']);
```

### Invokable Class

[](#invokable-class)

```
$router->get('/users', UserAction::class);
```

### Closure

[](#closure)

```
$router->get('/users', function(array $params) {
    echo 'Users';
});
```

**Note**: Closures cannot be cached due to PHP serialization limitations.

Performance
-----------

[](#performance)

The router uses a three-level indexing strategy for optimal performance:

1. **Static Index (O(1))**: Hash map `method:path` → Route for exact matches
2. **Prefix Index (O(1) + O(n))**: Hash map `method:prefix` → \[Routes\] for common prefixes
3. **Method Index (O(n))**: Hash map `method` → \[Routes\] as fallback

This approach minimizes regex matching for most common routing patterns.

Testing
-------

[](#testing)

```
composer test
```

License
-------

[](#license)

MIT License. See [LICENSE](LICENSE) for details.

Contributing
------------

[](#contributing)

Contributions are welcome! Please submit pull requests to the [GitHub repository](https://github.com/zero-to-prod/http-router).

Support
-------

[](#support)

- **Issues**: [GitHub Issues](https://github.com/zero-to-prod/http-router/issues)
- **Email**:
- **Documentation**:

Credits
-------

[](#credits)

Created and maintained by [David Smith](https://davidsmith.blog/).

###  Health Score

29

—

LowBetter than 60% of packages

Maintenance75

Regular maintenance activity

Popularity12

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity19

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

152d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/502649f05d36c87d494988bd99193a4d908d345335d99c080928a726277371f5?d=identicon)[zero-to-prod](/maintainers/zero-to-prod)

---

Top Contributors

[![zero-to-prod](https://avatars.githubusercontent.com/u/61474950?v=4)](https://github.com/zero-to-prod "zero-to-prod (3 commits)")

---

Tags

httpmiddlewarerouterroutingpsr-15http-routerzero-to-prod

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/zero-to-prod-http-router/health.svg)

```
[![Health](https://phpackages.com/badges/zero-to-prod-http-router/health.svg)](https://phpackages.com/packages/zero-to-prod-http-router)
```

###  Alternatives

[mezzio/mezzio-authentication

Authentication middleware for Mezzio and PSR-7 applications

121.6M26](/packages/mezzio-mezzio-authentication)[northwoods/router

Fast router for PSR-15 request handlers

161.4k](/packages/northwoods-router)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
