PHPackages                             hotaruma/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. hotaruma/http-router

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

hotaruma/http-router
====================

Simple http router

v0.7.0(2y ago)015MITPHPPHP &gt;=8.1

Since Jun 8Pushed 2y ago1 watchersCompare

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

READMEChangelog (6)Dependencies (4)Versions (12)Used By (0)

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

[](#http-router)

[![Build and Test](https://github.com/hotaruma/http-router/actions/workflows/ci.yml/badge.svg)](https://github.com/hotaruma/http-router/actions/workflows/ci.yml)[![Latest Version](https://camo.githubusercontent.com/1bde168a019240ac8dbb49d0fd3e83a789059922b6b341971028dd60d7420452/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f686f746172756d612f687474702d726f757465722e737667)](https://github.com/hotaruma/http-router/releases)[![License](https://camo.githubusercontent.com/83ce17a3452990f754f56efcc9b419e9120c8ec5f58a5a25c363457178a3eeac/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f686f746172756d612f687474702d726f757465722e737667)](https://github.com/hotaruma/http-router/blob/master/LICENSE)[![PHP from Packagist](https://camo.githubusercontent.com/f77408c63871915f88c8cb40dbd0ce68c6c00bc21e95aa5b0e6598ec3750706e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f686f746172756d612f687474702d726f75746572)](https://camo.githubusercontent.com/f77408c63871915f88c8cb40dbd0ce68c6c00bc21e95aa5b0e6598ec3750706e/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f686f746172756d612f687474702d726f75746572)[![Packagist Downloads](https://camo.githubusercontent.com/44485792a4531cae5c0f775fa655855ec9c74558f36843b90f7a07849c444e9d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f686f746172756d612f687474702d726f757465722e737667)](https://packagist.org/packages/hotaruma/http-router)[![codecov](https://camo.githubusercontent.com/242b24e5209e36b79d9fb0beeb8b2a82b3c99f5e66f319452e49fa7a2b3428c7/68747470733a2f2f636f6465636f762e696f2f67682f686f746172756d612f687474702d726f757465722f6272616e63682f6d61696e2f67726170682f62616467652e737667)](https://codecov.io/gh/hotaruma/http-router)

Simple HTTP router.

Navigation
----------

[](#navigation)

- [Installation](#installation)
- [RouteMap](#routemap)
    - [Route Parameters](#route-parameters)
    - [Route Config](#route-config)
    - [Pattern Registry](#pattern-registry)
    - [Grouping Routes](#grouping-routes)
    - [Route Scanner](#route-scanner)
- [Route Dispatcher](#route-dispatcher)
- [URL Generator](#url-generator)
- [Contributing](#contributing)

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

[](#installation)

You can install the library using Composer. Run the following command:

```
composer require hotaruma/http-router
```

RouteMap
--------

[](#routemap)

### Creating Routes

[](#creating-routes)

To create routes, you need to use the `RouteMap` class. Here's an example of creating a route:

```
use Hotaruma\HttpRouter\RouteMap;

$routeMap = new RouteMap();

$routeMap->get('/hello', function () {
    echo 'Hello, world!';
});

$routeMap->post('/users', UserController::class);
```

### Route Parameters

[](#route-parameters)

You can also define route parameters using curly braces `{}` in the route path:

```
$routeMap->get('/shop/{category}', CategoryController::class);
```

### Route Config

[](#route-config)

Routes can be configured by defining its defaults, rules, and more.

- **Defaults**: This sets the placeholder's value when generating a route by name, as long as there is no attribute with the same name in the route. In that case, the attribute's value takes precedence.
- **Rules**: These play a role in pattern validation within `{}` placeholders. They determine if a parameter matches a specific type based on regular expressions or `Closure`. Rules are also used to validate parameters during route generation.
- **Middlewares**: Middleware functions can be grouped and returned in their original form.
- **Name**: This is used to generate a route later on.
- **Methods**: Methods define whether a route matches the current request.

```
$routeMap->add('/news/{category:[A-Za-z]+}/{id}', NewsController::class)->config(
    defaults: ['category' => 'archive', 'id' => '1'],
    rules: ['id' => '\d+'],
    middlewares: [LogMiddleware::class],
    name: 'newsPage',
    methods: [AdditionalMethod::ANY],
);
```

It is preferable to use named attributes for configuration. By using named attributes, you can explicitly specify the purpose of each configuration option, improving the readability of your code.

### Pattern Registry

[](#pattern-registry)

The patterns can be defined in both the `rules` array and directly within the route path declaration. When patterns are defined in the `rules` array, they take precedence. Patterns are enclosed in curly braces `{}` follow the format `{placeholder:rule}`. Here's an example:

```
$routeMap->group(
    rules: ['id' => 'int'],
    group: function (RouteMapInterface $routeMap) {

        $routeMap->get('/users/{id}', UserController::class . '@show');
        $routeMap->get('/post/{category:slug}', PostController::class . '@show');
    }
);
```

In this example, `rules` array defines the pattern `id:\d+` and `{category:slug}` placeholder specifies that the `category` parameter in the URL should be a `[A-Za-z0-9-_]+`.

By default, we have the following rules:

```
$patterns = [
    'int' => '\d+',
    'alpha' => '[A-Za-z]+',
    'alnum' => '[A-Za-z0-9]+',
    'slug' => '[A-Za-z0-9-_]+',
    'uuid' => '[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}',
]
```

You can also define your own patterns and register them in the pattern registry. The patterns in the registry can be either regular expression strings or `Closures` that perform custom validation. Here's an example:

```
use \Hotaruma\HttpRouter\PatternRegistry\PatternRegistry;
use \Hotaruma\HttpRouter\RouteDispatcher;

$routeDispatcher = new RouteDispatcher();
$patternRegistry = new PatternRegistry();
$routeMap = new RouteMap();

$routeMap->get('/category/{tag:custom}/', stdClass::class);

$patternRegistry->addPattern('custom', '\w{3}');

$routeDispatcher->config(
    requestHttpMethod: HttpMethod::tryFrom($serverRequest->getMethod()),
    requestPath: $serverRequest->getUri()->getPath(),
    routes: $routeMap->getRoutes(),
    patternRegistry: $patternRegistry
);

$route = $routeDispatcher->match();
```

In this example, we register a custom pattern named 'custom' using a `Closure` that performs the validation.

```
$patternRegistry->addPattern('custom', static function (string $value, PatternRegistryInterface $patternRegistry): bool {
    return is_numeric($value);
});
```

If a route specifies both a rule in the route path and a rule in the route configuration, the rule in configuration takes precedence.

### Grouping Routes

[](#grouping-routes)

You can group routes with a common prefix and apply shared middleware or other configurations:

```
$routeMap->group(
    rules: ['slug' => '\w+', 'id' => '\d+'],
    namePrefix: 'question',
    methods: [HttpMethod::GET],
    group: function (RouteMapInterface $routeMap) {

        $routeMap->add('/questions/{slug}', [QuestionController::class, 'view']);
        $routeMap->add('/users/{id}', [UserController::class, 'view']);

        $routeMap->group(
            namePrefix: 'admin',
            pathPrefix: 'admin',
            middlewares: [LogMiddleware::class, AccessMiddleware::class],
            methods: [HttpMethod::DELETE, HttpMethod::POST],
            group: function (RouteMapInterface $routeMap) {

                $routeMap->add('/questions/{id}', AdminQuestionController::class);
                $routeMap->add('/users/{id}', AdminUserController::class);
            }
        );
    }
);
```

When grouping routes and nesting one group within another, you have the ability to merge configurations. This means that each route inside a group merges its configuration with the group's configuration, and each nested group merges its configuration with its parent group.

By organizing routes into groups, you can apply specific configurations to multiple routes at once. The configurations cascade down the nested groups, allowing you to inherit and override settings as needed. This provides a powerful and flexible way to manage and organize your routes.

```
$routeMap->group(
    pathPrefix: 'admin',
    methods: [HttpMethod::GET],
    middlewares: [ManagerAccessMiddleware::class],
    group: function (RouteMapInterface $routeMap) {

        $routeMap->add('/dashboard', [AdminController::class, 'dashboard']);

        $routeMap->changeGroupConfig(
            middlewares: [AdminAccessMiddleware::class],
            methods: [HttpMethod::GET, HttpMethod::DELETE, HttpMethod::POST],
        );

        $routeMap->add('/users/{id}', [AdminController::class, 'users']);
        $routeMap->add('/settings', [AdminController::class, 'settings']);
    }
);
```

### Route Scanner

[](#route-scanner)

By using PHP 8's attribute syntax, you can easily annotate your classes and methods with route attributes, simplifying the process of defining routes in your application.

```
use Hotaruma\HttpRouter\Attribute\{Route, RouteGroup};
use Hotaruma\HttpRouter\Enum\HttpMethod;

#[RouteGroup(pathPrefix: '/users', methods: [HttpMethod::GET])]
class ApiUserController
{
    #[Route('/')]
    public function getUsers()
    {
        // Handle getting users
    }

    #[Route('/{id}', rules: ['id' => '\d+'])]
    public function getUserById(int $id)
    {
        // Handle getting a user by ID
    }
}
```

The Route Scanner scans the provided classes for attributes that extend the `RouteInterface` and `RouteGroupInterface`. It extracts the route configuration from these attributes and registers the routes in the `RouteMap`, a data structure that holds all the defined routes.

By calling the `scanRoutes` method of the `RouteScanner` class and passing the `ApiController` class as an argument, the routes defined in the class will be scanned and registered in the `RouteMap`.

```
use Hotaruma\HttpRouter\RouteScanner\RouteScanner;

$routeScanner = new RouteScanner();

$routeMap = $routeScanner->scanRoutes(ApiController::class);
$routes = $routeMap->getRoutes();
// ...
```

The Route Scanner can be used within the `RouteMap` and its groups.

```
use Hotaruma\HttpRouter\RouteMap;

$routeMap = new RouteMap();

$routeMap->scanRoutes(UserController::class, PostController::class);

$routeMap->group(
    pathPrefix: 'admin',
    middlewares: [AdminAccessMiddleware::class],
    group: function (RouteMapInterface $routeMap) {

        $routeMap->scanRoutes(AdminController::class);
    }
);
```

When scanning routes using `$routeMap->scanRoutes()` and encountering the `RouteGroup` attribute, the configuration defined within the attribute will take precedence over the current group configuration set by `$routeMap->group()`. This means that the configuration specified in `RouteGroup` will be used for the routes within that specific class.

The `routeActionBuilder` method allows you to customize how the action for a created route will look like, based on the class name and method name. This can be useful if you want to modify the default behavior of action generation for the routes.

```
$routeScanner->routeActionBuilder(function (string $className, string $methodName): array {
    return "$className@$methodName";
});
```

The `scanRoutesFromDirectory` function allows you to scan all PHP files in a specified directory and its subdirectories to automatically discover classes and their attributes marked with the `Route` and `RouteGroup` attributes.

```
use Hotaruma\HttpRouter\RouteScanner\RouteScanner;

$routeScanner = new RouteScanner();
$directoryPath = __DIR__ . '/Controllers';

$routeMap = $routeScanner->scanRoutesFromDirectory($directoryPath);
$routes = $routeMap->getRoutes();
```

Route Dispatcher
----------------

[](#route-dispatcher)

Once the routes are defined, you can use the `RouteDispatcher` class to match the incoming request to the appropriate route and extract the associated attributes. You can configure the `RouteDispatcher` and match the routes:

```
use Hotaruma\HttpRouter\{RouteMap,RouteDispatcher};

$routeDispatcher = new RouteDispatcher();
$routeMap = new RouteMap();

$routeMap->get('/home', HomeController::class);
$routeMap->post('/contacts', ContactsController::class);

$routeDispatcher->config(
    requestHttpMethod: HttpMethod::tryFrom($serverRequest->getMethod()),
    requestPath: $serverRequest->getUri()->getPath(),
    routes: $routeMap->getRoutes(),
);

try {
    $route = $routeDispatcher->match();
} catch (RouteDispatcherNotFoundException $exception) {
    // exception handling
}

$attributes = $route->getAttributes();
$action = $route->getAction();
```

You can customize the route dispatching process by providing your own implementation of the `RouteMatcherInterface`interface.

```
$routeDispatcher->routeMatcher(new RouteMatcher());
```

URL Generator
-------------

[](#url-generator)

To use the `RouteUrlGenerator`, you need to create a `RouteMap` instance with defined routes.

```
use Hotaruma\HttpRouter\{RouteMap, RouteUrlGenerator};

$routeUrlGenerator = new RouteUrlGenerator();
$routeMap = new RouteMap();

$routeMap->get('/profile/{category}/', stdClass::class)->config(
    rules: ['category' => '\w+'],
    defaults: ['category' => 'projects'],
    name: 'profile',
);

$routeUrlGenerator->config(
    routes: $routeMap->getRoutes(),
);
$route = $routeUrlGenerator->generateByName('profile');
$url = $route->getUrl(); //profile/projects/
```

You can customize the route url generation by providing your own implementation of the `RouteUrlBuilderInterface`interface.

```
$routeUrlGenerator->routeUrlBuilder(new RouteUrlBuilder());
```

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

[](#contributing)

Contributions are welcome! If you find a bug or have an idea for a new feature, please open an issue or submit a pull request.

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 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

Every ~3 days

Total

10

Last Release

1035d ago

PHP version history (2 changes)v0.1.0PHP &gt;=8.2

v0.6.1PHP &gt;=8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/5f5080e0a006b5fda1d8d127ba8ce022e2882e5b613f4a7455d775848c70d60a?d=identicon)[hotaruma](/maintainers/hotaruma)

---

Top Contributors

[![hotaruma](https://avatars.githubusercontent.com/u/29927576?v=4)](https://github.com/hotaruma "hotaruma (71 commits)")

---

Tags

phprouterphprouter

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/hotaruma-http-router/health.svg)

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

###  Alternatives

[aphiria/aphiria

The Aphiria framework

1427.7k2](/packages/aphiria-aphiria)[wilaak/radix-router

High-performance radix tree based HTTP request router

612.8k5](/packages/wilaak-radix-router)[eftec/routeone

Router service class for PHP

291.4k2](/packages/eftec-routeone)[divineniiquaye/flight-routing

Flight routing is a simple, fast PHP router that is easy to get integrated with other routers.

152.5k](/packages/divineniiquaye-flight-routing)

PHPackages © 2026

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