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

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

chevere/router
==============

PSR-7/11/15/17 compatible PHP library for creating HTTP routing systems

0.9.1(5mo ago)44.1k↓33.3%[1 issues](https://github.com/chevere/router/issues)5Apache-2.0PHPPHP ^8.1CI failing

Since Dec 5Pushed 2mo ago1 watchersCompare

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

READMEChangelog (10)Dependencies (15)Versions (23)Used By (5)

Router
======

[](#router)

[![Chevere](chevere.svg)](chevere.svg)

[![Build](https://camo.githubusercontent.com/f0a90519c6251b7942c552ae55d539d1cd8e313e30cf18f2ce9ed400ad6227a8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f636865766572652f726f757465722f746573742e796d6c3f6272616e63683d302e3130267374796c653d666c61742d737175617265)](https://github.com/chevere/router/actions)[![Code size](https://camo.githubusercontent.com/b1cafdc048a19b09d17e73183a341367e405b8dd83d86ba27ccd24d3253809a2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c616e6775616765732f636f64652d73697a652f636865766572652f726f757465723f7374796c653d666c61742d737175617265)](https://camo.githubusercontent.com/b1cafdc048a19b09d17e73183a341367e405b8dd83d86ba27ccd24d3253809a2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c616e6775616765732f636f64652d73697a652f636865766572652f726f757465723f7374796c653d666c61742d737175617265)[![Apache-2.0](https://camo.githubusercontent.com/239290dd517a4e023b64cdbdaa55a7d1bdcf43198e1593c282548764beeca1a2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f636865766572652f726f757465723f7374796c653d666c61742d737175617265)](LICENSE)[![PHPStan](https://camo.githubusercontent.com/6016298b28550819030c76e9327f62501596a31fd76406695bae2f3d2a1f26a4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230392d626c756576696f6c65743f7374796c653d666c61742d737175617265)](https://phpstan.org/)[![Mutation testing badge](https://camo.githubusercontent.com/61334d4c0f976e41c28a4e1939f215c49622d0129cff1b45eee7457e7e4f25f2/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742d7371756172652675726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d25324663686576657265253246726f75746572253246302e3130)](https://dashboard.stryker-mutator.io/reports/github.com/chevere/router/0.10)

[![Quality Gate Status](https://camo.githubusercontent.com/3ac0a2fd2f0474ad52332f90cf208f6f561716aafd1e25e0affddc9297dcc4ba/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636865766572655f726f75746572266d65747269633d616c6572745f737461747573)](https://sonarcloud.io/dashboard?id=chevere_router)[![Maintainability Rating](https://camo.githubusercontent.com/64b405806b6edb0d4239f128ab570212db6969c9745d6a8beac7011418a8f33d/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636865766572655f726f75746572266d65747269633d7371616c655f726174696e67)](https://sonarcloud.io/dashboard?id=chevere_router)[![Reliability Rating](https://camo.githubusercontent.com/76026bd4380f54c9d61f5c82ee8d69d59e7150fbfc882f3dc58b3a69188f8297/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636865766572655f726f75746572266d65747269633d72656c696162696c6974795f726174696e67)](https://sonarcloud.io/dashboard?id=chevere_router)[![Security Rating](https://camo.githubusercontent.com/7046a89e29e62e60724c438d83f0b207004ec13aabc5b21ee1fb204778b03eeb/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636865766572655f726f75746572266d65747269633d73656375726974795f726174696e67)](https://sonarcloud.io/dashboard?id=chevere_router)[![Coverage](https://camo.githubusercontent.com/b67f3da357021932e84ad0a2121c940b25db6f10140a4e02cbb7b3aca470cef9/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636865766572655f726f75746572266d65747269633d636f766572616765)](https://sonarcloud.io/dashboard?id=chevere_router)[![Technical Debt](https://camo.githubusercontent.com/29b327639312c38b2665cfa968bb40a1e5ed1f26e419fe09ab097328226c1e4c/68747470733a2f2f736f6e6172636c6f75642e696f2f6170692f70726f6a6563745f6261646765732f6d6561737572653f70726f6a6563743d636865766572655f726f75746572266d65747269633d7371616c655f696e646578)](https://sonarcloud.io/dashboard?id=chevere_router)[![CodeFactor](https://camo.githubusercontent.com/366254e1dd4248fa515df037b718580524c80f1177669103130ff7f0f54b6a5c/68747470733a2f2f7777772e636f6465666163746f722e696f2f7265706f7369746f72792f6769746875622f636865766572652f726f757465722f6261646765)](https://www.codefactor.io/repository/github/chevere/router)

Summary
-------

[](#summary)

Router is a library for creating routing systems for [chevere/http](https://chevere.org/packages/http). It is compatible with the following [PHP-FIG](https://www.php-fig.org) PSR:

- PSR-7: HTTP message interfaces
- PSR-11: Container interface
- PSR-15: HTTP Server Request Handlers
- PSR-17: HTTP Factories

Installing
----------

[](#installing)

Router is available through [Packagist](https://packagist.org/packages/chevere/router) and the repository source is at [chevere/router](https://github.com/chevere/router).

```
composer require chevere/router
```

Quick start
-----------

[](#quick-start)

```
// Define routes
$routes = routes(
    route('/hello', GET: 'hello.twig'),
    route('/api/users',
        GET: UserListController::class,
        POST: headless(UserCreateController::class, CsrfMiddleware::class)
    ),
    route('/products/{id}',
        GET: bind('product.twig', ProductGetController::class),
        PUT: ProductUpdateController::class,
        DELETE: ProductDeleteController::class
    )
);
// Create router
$router = router($routes);
// Handle request
$routed = $router->routed($serverRequest, $responseFactory, $container);
$response = $routed->response();
$return = $routed->return(); // Controller return value
```

What it does
------------

[](#what-it-does)

The Router library allows you to bind paths to HTTP methods and logic. It maps paths to their corresponding HTTP controller actions, views, and middleware pipelines. It also collects and validates the views and dependencies used in the routing process.

For example, to resolve this:

```
GET /product/123
    -> ProductGet->__invoke(123):context
    -> product.twig

DELETE /product/123
    -> ProductDelete->__invoke(123)

```

You need to write the following route code:

```
$route = route(
    '/product/{id}',
    GET: bind('product.twig', ProductGet::class),
    DELETE: ProductDelete::class,
);
```

And the HTTP controllers may look like this:

```
class ProductGet extends Controller
{
    public function __invoke(string $id): array
    {
        // ...
        return $context;
    }
}

class ProductDelete extends Controller
{
    public function __invoke(string $id): void
    {
        // ...
    }
}
```

Bind
----

[](#bind)

A Bind is the conjunction of a controller, its middleware pipeline and a view. Use helper function `bind($view, $controller, ...$middleware)` to explicitly create a binding.

```
$bind = bind(
    view: 'product.twig',
    controller: ProductGet::class,
    ...$middleware // PSR-15
)
```

Use method `controllerName()` to access the ControllerName API.

```
$bind->controllerName(); // ProductGet
```

Use method `view()` to access the view string.

```
$bind->view(); // product.twig
```

Use method `middlewares()` to access the Middlewares collection API.

```
$bind->middlewares();
```

Headless
--------

[](#headless)

Use helper function `headless($controller, ...$middleware)` to define a [bind](#bind) without a view, only the controller and middleware.

```
headless(ProductGet::class, ...$middleware)
```

Route
-----

[](#route)

Use the helper function `route($path, ...)` to define path endpoints. An endpoint is defined as the conjunction of a path, an HTTP method and a controller.

```
route('/hello-world', GET: ..., POST: ...)
```

### View route

[](#view-route)

When no controller is needed you can bind the HTTP method to the target view, without indicating a controller.

```
route('/', GET: 'home.twig')
```

### Headless route

[](#headless-route)

When no view is needed you can bind the HTTP method to the target controller, without indicating a view.

```
route(
    '/product/{id}',
    DELETE: ProductDelete::class,
)
```

### Dynamic route

[](#dynamic-route)

Dynamic routes use variable wildcards (`{variable}` syntax) to denote variable path components.

```
route('/products/{id}', GET: MyController::class);
```

Where `MyController` class method `__invoke()` parameters must match the defined wildcards:

```
public function __invoke(string $id) {...}
```

Path variables implicit match against `[^/]+`. To customize use `_string` on main’s function parameters.

```
use Chevere\Parameter\Attributes\_string;

public function __invoke(
    #[_string('/\d+/')]
    string $id
) {
    // $id is digits only
}
```

### The `view` argument

[](#the-view-argument)

Use the `view` argument to define the same view for all endpoints.

```
route(
    '/login',
    view: 'login.twig',
    GET: LoginGet::class,
    POST: LoginPost::class,
)
```

Use helpers like `bind()` or `headless()` to override the base `view` argument definition.

### The `middleware` argument

[](#the-middleware-argument)

Use the `middleware` argument to define the same middleware pipeline for all endpoints.

```
route(
    '/signup',
    view: 'signup.twig',
    middleware: middlewares(
        RedirectIfLogged::class, // PSR-15
        TurnstileVerify::class, // PSR-15
    ),
    GET: SignUpGet::class,
    POST: SignUpPost::class,
)
```

Use helpers like `bind()` or `headless()` to override the base `middleware` argument definition.

### The `exclude` argument

[](#the-exclude-argument)

The `exclude` argument enables to define middleware names that should be excluded from the pipeline.

```
route(
    '/logout',
    exclude: middlewares(
        TurnstileVerify::class, // PSR-15
        ChallengeTwoFactor::class, // PSR-15
    ),
    POST: LogoutPost::class,
)
```

Middlewares
-----------

[](#middlewares)

The Middlewares API enables you to organize PSR-15 middleware for your routes. Use the helper function `middlewares(...$middleware)` to create a Middlewares collection.

```
$middlewares = middlewares(
    SessionMiddleware::class,
    AuthMiddleware::class
);
```

You can use this collection in route definitions to apply middleware to specific routes.

Routes
------

[](#routes)

The Routes API enables to collect, assert, inspect and organize Route objects.

Use helper function `routes(...$route|$routes)` to create a Routes object.

```
$routes = routes(
    route(...),
    routes(...),
);
```

### Managing routes

[](#managing-routes)

Use method `withRoute(...$route)` to add Route objects, use method `withRoutes(...$routes)` to add Routes objects.

```
$routes = $routes->withRoute($route);
$routes = $routes->withRoutes($moreRoutes);
```

Use method `has(...$path)` to tell if the path is already routed. Use `get($path)` to retrieve the route for a given path.

```
$routes = $routes->has('/pricing'); // bool
$home = $routes->get('/pricing'); // RouteInterface
```

### Middleware pipelines

[](#middleware-pipelines)

Use method `withPrependMiddleware($midlewares)` to prepend middleware to the begin of the pipeline. Use this for middleware that must resolve early in execution order.

```
$routes = $routes->withPrependMiddleware(
    middlewares(
        SessionSetUpCSRFToken::class, // PSR-15
    )
)
```

Use method `withAppendMiddleware($middlewares)` to append middleware to the end of the pipeline. Use this for middleware that must resolve last in execution order.

```
$routes = $routes->withAppendMiddleware(
    middlewares(
        SessionCheckCSRFToken::class, // PSR-15
    )
)
```

Views
-----

[](#views)

The Views API enables to assert the views collected for all routes. Use `assert($viewsDir)` method to assert that the views directory contains the view names defined in routes.

```
$router->views()->assert($viewsDir);
```

Container
---------

[](#container)

Use `new Container(...)` to create the dependency container by passing entries you may need to manually create.

```
$container = new Container(
    database: $database,
    // other entries
);
```

### Adding entries

[](#adding-entries)

Use method `with(...$entries)` to add one or more named entries to the container.

```
$container = $container->with(
    status: 'challenged',
    challenge: '2fa',
);
```

### Accessing entries

[](#accessing-entries)

Use method `has($name)` to tell if the container has an entry by name. Use method `get($name)` to retrieve the entry value.

```
$container->has('session'); // bool true
$session = $container->get('session'); // SessionInterface
```

### Automatic dependency injection

[](#automatic-dependency-injection)

Use method `withAutoInject($deps, ...$ignore)` to automatically inject missing dependencies recursively.

```
$container = $container->withAutoInject($deps, ...$ignore);
```

The `ignore` argument allows you to define dependencies that should be ignored, which is useful for dependencies that must be [late injected](#late-dependency-injection) after the middleware pipeline resolves.

Dependencies
------------

[](#dependencies)

The Dependencies API enables to interact with the dependencies detected for all routing participants. The Router will collect every `__construct` on both controllers and middleware, to provide a collection where you can use your own dependency injection logic.

```
$deps = $router->dependencies();
```

### Assert dependencies

[](#assert-dependencies)

Use method `assert($container)` to assert that the PSR-11 `$container` meets the required dependencies.

```
$deps->assert($container);
```

This is an additional guard that can be used to static detect missing dependencies. On runtime, the system will throw an exception before even reach the middleware layer.

Routed
------

[](#routed)

The Routed API enables to interact with the outcome result of the routing process. Use method `routed(...)` to resolve routing.

```
$routed = $router->routed(
    $serverRequest,   // PSR-7
    $responseFactory, // PSR-17
    $container,       // PSR-11
    $callback
);
```

### Late dependency injection

[](#late-dependency-injection)

The `$callback` argument enables to pass logic that will resolve after the middleware pipeline and before the controller layer.

```
use Chevere\Router\Interfaces\ContainerInterface;

$callback = function (ContainerInterface $container): ContainerInterface {
    $session = $container->get('sessionFactory')->newSession(
        $container->get('requestUser')->sessionId
    );

    return $container->with(
        session: $session,
        user: $session->getOrDefault('user')
    );
};
```

### Routed outcome

[](#routed-outcome)

Use method `hasThrowable()` to tell if routing throws an exception. Use method `throwable()` to access the exception (if any).

```
$hasThrowable = $routed->hasThrowable(); // bool
$throwable = $routed->throwable();
```

The system is flexible as it enables to define catch-all strategies. For example, you may want to catch `ControllerException` objects and pass-by everything else.

```
if ($routed->hasThrowable()
    && ! ($routed->throwable() instanceof ControllerException)
) {
    throw $routed->throwable();
}
```

Use method `response()` to access the routed PSR-7 response object.

```
$psr7Response = $routed->response();
```

Use method `bind()` to access the routed [Bind](#bind) API, which enables to tell the controller, view and middleware.

```
$bind = $routed->bind();
```

Use method `return()` to access to the controller return value. This is the value after Action I/O guard layer.

```
$controllerReturn = $routed->return();
```

Documentation
-------------

[](#documentation)

Documentation is available at [chevere.org](https://chevere.org/packages/router).

License
-------

[](#license)

Copyright [Rodolfo Berrios A.](https://rodolfoberrios.com/)

Chevere is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for the full license text.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

###  Health Score

45

—

FairBetter than 92% of packages

Maintenance79

Regular maintenance activity

Popularity25

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity54

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 ~53 days

Total

23

Last Release

76d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/a87fbbcb1518fe64878bc53dedd9f61b81243cbb21b73c26f5e299d501375984?d=identicon)[rodolfo](/maintainers/rodolfo)

---

Top Contributors

[![rodber](https://avatars.githubusercontent.com/u/20590102?v=4)](https://github.com/rodber "rodber (304 commits)")

---

Tags

cheverephp

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleECS

Type Coverage Yes

### Embed Badge

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

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

###  Alternatives

[api-platform/core

Build a fully-featured hypermedia or GraphQL API in minutes!

2.6k48.1M234](/packages/api-platform-core)[chevere/workflow

Declarative workflow engine for PHP with automatic dependency resolution, sync/async job execution, and type-safe response chaining.

1111.8k1](/packages/chevere-workflow)[api-platform/state

API Platform state interfaces

223.4M57](/packages/api-platform-state)[chevere/parameter

Dynamic parameter-argument validation for PHP with rich type constraints, attributes, and schema introspection.

1023.7k20](/packages/chevere-parameter)[chevere/chevere

High quality library for building modern PHP

9718.9k4](/packages/chevere-chevere)[mezzio/mezzio-fastroute

FastRoute integration for Mezzio

162.7M52](/packages/mezzio-mezzio-fastroute)

PHPackages © 2026

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