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

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

quimcalpe/router
================

Regexp based Router, easy to use and with a rich feature set

4.2.0(2mo ago)37.7k↑356.3%1MITPHPPHP &gt;=8.5CI passing

Since May 22Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/quimcalpe/router)[ Packagist](https://packagist.org/packages/quimcalpe/router)[ Docs](https://github.com/quimcalpe/router)[ RSS](/packages/quimcalpe-router/feed)WikiDiscussions master Synced yesterday

READMEChangelog (10)Dependencies (9)Versions (24)Used By (0)

quimcalpe/router
================

[](#quimcalperouter)

[![Version](https://camo.githubusercontent.com/725cc572c9621b1f53e05c57a2a0cb46871af03a854a8d930cbe74dd3c1a9902/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7175696d63616c70652f726f757465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/quimcalpe/router)[![License](https://camo.githubusercontent.com/518406d52d58cad724bb2d2e93785095c7256e125d589f5107f9f3f92bc6da13/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f7175696d63616c70652f726f757465722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/quimcalpe/router)[![Tests](https://github.com/quimcalpe/router/actions/workflows/tests.yml/badge.svg)](https://github.com/quimcalpe/router/actions/workflows/tests.yml)

Regexp based Router, easy to use and with a rich feature set. It includes various built-in dispatchers, and we also provide an interface to develop fully customized dispatchers for your project.

Install
-------

[](#install)

Via Composer

```
$ composer require quimcalpe/router
```

Requirements
------------

[](#requirements)

The following versions of PHP are supported by this version.

- PHP 8.5

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

[](#basic-usage)

```
// Require composer autoloader
require __DIR__ . '/vendor/autoload.php';

use QuimCalpe\Router\Router;
use QuimCalpe\Router\Dispatcher\SimpleDispatcher;

// Create Router instance
$router = new Router();

// Define routes, last parameter defining route name is optional
$router->addRoute('GET', '/users', 'Quimi\Controllers\UserController', 'user_list');
$router->addRoute('GET', '/users/edit/{id:number}', 'Quimi\Controllers\UserController::edit', 'user_edit');
$router->addRoute(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\Controllers\UserController::remove', 'user_delete');

// Sugar methods for common verbs are also available (GET, POST, PUT, DELETE...)
$router->addGet('/user/{id}', 'Quimi\Controllers\UserController::show', 'user_show');

// You can also create a QuimCalpe\Router\Route\Route value object and add directly to router's `->add()`
$route = new Route('GET', '/', 'Quimi\Controllers\HomeController', 'home');
$router->add($route);

try {
    // Match routes
    $route = $router->parse($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
    // Dispatch route
    $dispatcher = new SimpleDispatcher();
    $response = $dispatcher->handle($route);
} catch (QuimCalpe\Router\Exception\MethodNotAllowedException $e) {
	header('HTTP/1.0 405 Method Not Allowed');
	// exception message contains allowed methods
	header('Allow: '.$e->getMessage());
} catch (QuimCalpe\Router\Exception\RouteNotFoundException $e) {
	header('HTTP/1.0 404 Not Found');
    // not found....
}
```

Constructor optional Route\[\] parameter
----------------------------------------

[](#constructor-optional-route-parameter)

You can alternatively pass an array of `Route` objects to Router's constructor, and routes will be created;

```
use QuimCalpe\Router\Router;
use QuimCalpe\Router\Route\Route;

$routes = [
	new Route('GET', '/users', 'Quimi\Controllers\UserController', 'user_list'),
	new Route('GET', '/users/edit/{id:number}', 'Quimi\Controllers\UserController::edit', 'user_edit'),
	new Route(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\Controllers\UserController::remove', 'user_delete'),
]

$router = new Router($routes);
```

This array can be included from another file, enabling config separation in a simple way.

### Route Providers

[](#route-providers)

If you want to import a bunch of Routes from a specific package/namespace/bundle and you want to keep routes organized, you can use Route providers, define your provider like this:

```
namespace My\Package;

use QuimCalpe\Router\Route\Route;
use QuimCalpe\Router\Route\RouteProvider;

class MyPackageRoutes implements RouteProvider
{
    public function routes(): array
    {
        return [
            new Route('GET', '/users', 'Quimi\Controllers\UserController', 'user_list'),
            new Route('GET', '/users/edit/{id:number}', 'Quimi\Controllers\UserController::edit', 'user_edit'),
            new Route(['POST', 'DELETE'], '/users/remove/{id:number}', 'Quimi\Controllers\UserController::remove', 'user_delete'),
        ];
    }
}
```

And then initialize the Router with:

```
$router = new Router();
$router->addRouteProvider(new \My\Package\MyPackageRoutes());
```

### Route Patterns

[](#route-patterns)

Basic regexp patterns are supported, some are already included:

- `[^/]+` as default
- 'word' =&gt; `\w+`
- 'number' =&gt; `\d+`
- 'slug' =&gt; `[A-Za-z0-9_-]+`

Patterns can be used this way:

```
$router->addRoute('GET', '/users/edit/{id:number}', 'Controller::action');
$router->addRoute('GET', '/users/{name:word}', 'Controller::action');
```

You can define your own patterns:

```
$router->addPattern("phone", "[0-9]-[0-9]{3}-[[0-9]{3}-[0-9]{4}"); // #-###-###-####
$router->addRoute("GET", "/customer/{phone:phone}", "Vendor\Package\Controller");
$parsedRoute = $router->parse("GET", "/customer/1-222-333-4444");
```

### Wildcards

[](#wildcards)

Wildcards in routes can be used with `WildcardDispatcher`:

```
$router->addRoute('GET', '/test/{controller}/{action}/{id}', 'Vendor\Package\{controller}::{action}');
$parsedRoute = $router->parse("GET", "/test/user/edit");
$dispatcher = new WildcardDispatcher;
$response = $dispatcher->handle($parsedRoute); // => Vendor\Package\User::edit($id)
```

### Request Response

[](#request-response)

Standard Request - Response workflow with Symfony HttpFoundation components is supported with `RequestResponseDispatcher`:

```
use Symfony\Component\HttpFoundation\Request;
use QuimCalpe\Router\Router;
use QuimCalpe\Router\Dispatcher\RequestResponseDispatcher;

$router = new Router();
$router->addRoute('GET', '/users', 'Quimi\Controllers\UserController::index');

$request = Request::createFromGlobals();
$route = $router->parse($request->getMethod(), $request->getPathInfo());

// You can optionally modify the request object here before dispatching:
$request->attributes->set('foo', 'bar');

$dispatcher = new RequestResponseDispatcher($request);
$response = $dispatcher->handle($route);
$response->send();
```

### PSR-7 HTTP Message

[](#psr-7-http-message)

A built-in `PSR7Dispatcher` is available to work with PHP-FIG's PSR-7 HTTP Message standard implementations, an example using [Zend Diactoros](https://github.com/zendframework/zend-diactoros) and a simple [PSR-7 Response Sender](https://github.com/quimcalpe/psr7-response-sender) would look like this:

```
use QuimCalpe\Router\Router;
use QuimCalpe\Router\Route\Route;
use QuimCalpe\Router\Dispatcher\PSR7Dispatcher;
use function QuimCalpe\ResponseSender\send AS send_response;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response;

$router = new Router();
$router->add(new Route("GET", "/test", "ControllerFoo"));

$request = ServerRequestFactory::fromGlobals();
$route = $router->parse($request->getMethod(), $request->getUri()->getPath());

$dispatcher = new PSR7Dispatcher($request, new Response());
$response = $dispatcher->handle($route);
send_response($response);
```

### Custom Dispatcher

[](#custom-dispatcher)

You can create your custom Dispatcher, implementing `DispatcherInterface`:

```
interface DispatcherInterface
{
    public function handle(ParsedRoute $route): mixed;
}
```

`QuimCalpe\Router\Route\ParsedRoute` is a small Value Object with `controller()` and `params()` methods already parsed by `Router::parse`.

### Trailing slash

[](#trailing-slash)

Default behaviour is to honour distinction between routes with and wothout trailing slashes:

```
$router = new Router();
$router->addRoute('GET', '/users', 'Controller');
$router->parse('GET', '/users'); // => OK!
$router->parse('GET', '/users/'); // => NOT FOUND
```

You can disable this behaviour with `disableTrailingSlashCheck` method:

```
$router = new Router();
$router->addRoute('GET', '/users', 'Controller');
$router->disableTrailingSlashCheck();
$router->parse('GET', '/users'); // => OK!
$router->parse('GET', '/users/'); // => OK!
```

Testing
-------

[](#testing)

```
$ vendor/bin/phpunit
```

License
-------

[](#license)

The MIT License (MIT). Please see [License File](https://github.com/quimcalpe/router/blob/master/LICENSE.md) for more information.

###  Health Score

58

—

FairBetter than 98% of packages

Maintenance86

Actively maintained with recent releases

Popularity27

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity90

Battle-tested with a long release history

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

Recently: every ~406 days

Total

23

Last Release

66d ago

Major Versions

0.4.0 → 1.0.02015-11-26

1.2.1 → 2.0.02018-08-14

2.3.0 → 3.0.02023-04-26

3.0.0 → 4.0.02026-04-29

PHP version history (7 changes)0.1.0PHP &gt;=5.4.0

1.1.0PHP &gt;=5.6.0

2.0.0PHP ^7.1

2.2.0PHP ^7.3

2.3.0PHP &gt;=7.3

3.0.0PHP &gt;=8.1

4.0.0PHP &gt;=8.5

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1057151?v=4)[Quim Calpe](/maintainers/quimcalpe)[@quimcalpe](https://github.com/quimcalpe)

---

Top Contributors

[![quimcalpe](https://avatars.githubusercontent.com/u/1057151?v=4)](https://github.com/quimcalpe "quimcalpe (75 commits)")

---

Tags

phppsr-7routerroutingpsr-7uriroutedispatcher

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[guzzlehttp/psr7

PSR-7 message implementation that also provides common utility methods

8.0k1.1B4.0k](/packages/guzzlehttp-psr7)[api-platform/core

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

2.6k51.2M339](/packages/api-platform-core)[symfony/symfony

The Symfony PHP framework

31.4k87.2M2.2k](/packages/symfony-symfony)[moonshine/moonshine

Laravel administration panel

1.3k253.1k81](/packages/moonshine-moonshine)[symfony/psr-http-message-bridge

PSR HTTP message bridge

1.3k320.9M985](/packages/symfony-psr-http-message-bridge)[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)

PHPackages © 2026

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