PHPackages                             phoole/route - 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. phoole/route

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

phoole/route
============

Slim, fast and full compatible PSR-7 &amp; PSR-15 routing library for PHP

1.1.0(6y ago)318Apache-2.0PHPPHP &gt;=7.2.0CI failing

Since Oct 30Pushed 6y ago1 watchersCompare

[ Source](https://github.com/phoole/route)[ Packagist](https://packagist.org/packages/phoole/route)[ RSS](/packages/phoole-route/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (7)Dependencies (5)Versions (8)Used By (0)

route
=====

[](#route)

[![Build Status](https://camo.githubusercontent.com/b10ce0aa57ed7247e02fcf89d6387778123e9795b0be5eb9a4416eeb72f53d08/68747470733a2f2f7472617669732d63692e636f6d2f70686f6f6c652f726f7574652e7376673f6272616e63683d6d6173746572)](https://travis-ci.com/phoole/route)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/1eb7296f6335941ce111819ffb8a5f3b6b44cd6cd37c95e45f5c9bbbcb3dce6b/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f70686f6f6c652f726f7574652f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/phoole/route/?branch=master)[![Code Climate](https://camo.githubusercontent.com/67f2eb456013b4c2c57489645ab37c34af4f78410ffffdcacde37f684769c913/68747470733a2f2f636f6465636c696d6174652e636f6d2f6769746875622f70686f6f6c652f726f7574652f6261646765732f6770612e737667)](https://codeclimate.com/github/phoole/route)[![PHP 7](https://camo.githubusercontent.com/7c921fea1ba24c7fd55796f9a39498a68150a036ac479cc2019517fc3999f0cc/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f70686f6f6c652f726f757465)](https://packagist.org/packages/phoole/route)[![Latest Stable Version](https://camo.githubusercontent.com/0ede987c71f934f1eea944bb23aba8769ee7bcdb2d55456b04cf46976545d2ab/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f70686f6f6c652f726f757465)](https://packagist.org/packages/phoole/route)![License](https://camo.githubusercontent.com/ee2e477d9da7bacb6e5e9bc1d6a40b3f18a28bba77abe6b5bf2614a21363e269/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f70686f6f6c652f726f757465)

Slim, fast and full compatible PSR-7 &amp; PSR-15 routing library for PHP.

Why another routing library ?
-----------------------------

[](#why-another-routing-library-)

- [Super fast](#performance) using [fastRoute algorithm](#fastroute) algorithm.
- [Concise route syntax](#syntax). Route parameters and optional route segments.
- Built-in PSR-7 support.
- Out of box PSR-15 middleware.

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

[](#installation)

Install via the `composer` utility.

```
composer require "phoole/route"
```

or add the following lines to your `composer.json`

```
{
    "require": {
       "phoole/route": "1.*"
    }
}
```

Usage
--------------------------------------

[](#usage)

Inject route definitions (pattern, handler, default values etc.) into the dispatcher and then call either `match()` or `process()`.

```
use Phoole\Route\Router;
use GuzzleHttp\Psr7\ServerRequest;
use Psr\Http\Message\ServerRequestInterface;

$router = (new Router())
    ->addGet(
        '/blog/{action:xd}[/{year:d}[/{month:d}[/{date:d}]]]',
        function(ServerRequestInterface $request) {
            $params = $request->getAttribute(Router::URI_PARAMETERS);
            echo "action is " . $params['action'];
        }
    )->addPost(
        '/blog/post',
        'handler2'
    )->addRoute(new Route(
        'GET,HEAD',
        '/blog/read[/{id:d}]',
        'handler3',
        ['id' => '1'] // default values
    ));

// diaptcher (match & execute controller action)
$result = $router->match(new ServerRequest('GET', '/blog/list/2016/05/01'));

if ($result->isMatched()) {
    echo "WOW matched";
}
```

Or load routes from an array,

```
$routes = [
    ['GET', '/user/{action:xd}/{id:d}', 'handler1', ['id' => 1]],
    [ ... ],
    ...
];
$router = new Router($routes);
```

Route syntax
----------------------------------------------

[](#route-syntax)

- **{Named} parameters**

    A route pattern syntax is used where `{foo}` specifies a named parameter or a placeholder with name `foo` and default regex pattern `[^/]++`. In order to match more specific types, you may specify a custom regex pattern like `{foo:[0-9]+}`.

    ```
    // with 'action' & 'id' two named params
    $dispatcher->addGet('/user/{action:[^0-9/][^/]*}/{id:[0-9]+}', 'handler1');
    ```

    Predefined shortcuts can be used for placeholders as follows,

    ```
    ':d}'   => ':[0-9]++}',             // digit only
    ':l}'   => ':[a-z]++}',             // lower case
    ':u}'   => ':[A-Z]++}',             // upper case
    ':a}'   => ':[0-9a-zA-Z]++}',       // alphanumeric
    ':c}'   => ':[0-9a-zA-Z+_\-\.]++}', // common chars
    ':nd}'  => ':[^0-9/]++}',           // not digits
    ':xd}'  => ':[^0-9/][^/]*+}',       // no leading digits
    ```

    The previous pattern can be rewritten into,

    ```
    // with 'action' & 'id' two named params
    $router->addGet('/user/{action:xd}/{id:d}', 'handler1');
    ```
- **\[Optional\] segments**

    Optional segments in the route pattern can be specified with `[]` as follows,

    ```
    // $action, $year/$month/$date are all optional
    $pattern = '/blog[/{action:xd}][/{year:d}[/{month:d}[/{date:d}]]]';
    ```

    where optional segments can be **NESTED**. Unlike other libraries, optional segments are not limited to the end of the pattern, as long as it is a valid pattern like the `[/{action:xd}]` in the example.
- **Syntax limitations**

    - Parameter name *MUST* start with a character

        Since `{2}` has special meanings in regex. Parameter name *MUST* start with a character. And the use of `{}` inside/outside placeholders may cause confusion, thus is not recommended.
    - `[]` outside placeholder means *OPTIONAL* segment only

        `[]` can not be used outside placeholders as part of a regex pattern, *IF YOU DO NEED* to use them as part of the regex pattern, please include them *INSIDE* a placeholder.
    - Use of capturing groups `()` inside placeholders is not allowed

        Capturing groups `()` can not be used inside placeholders. For example `{user:(root|phoole)}` is not valid. Instead, you can use either use `{user:root|phoole}` or `{user:(?:root|phoole)}`.
- **Default Values**

    Default values can be added to named parameters at the end in the form of `{action:xd=list}`. Default values have to be alphanumeric chars. For example,

    ```
    // $action, $year/$month/$date are all optional
    $pattern = '/blog[/{action:xd=list}][/{year:d=2016}[/{month:d=01}[/{date:d=01}]]]';
    $router->addGet($pattern, 'handler');
    ```

Routes
----------------------------------------

[](#routes)

- **Same route pattern**

    User can define same route pattern with different http methods.

    ```
    $router
        ->addGet('/user/{$id}', 'handler1')
        ->addPost('/user/{$id}', 'handler2');
    ```

Handlers
-------------------------------------------

[](#handlers)

- **Handler resolving**

    Most of the time, matching route will return a handler like `[ 'ControllerName', 'actionName' ]`. Handler resolver can be used to resolving this pseudo handler into a real callable.

    Users may write their own handler resolver by implementing `Phoole\Route\Resolver\ResolverInterface`.

Algorithms

- **FastRoute algorithm**

    This *Fast Route algorithm* is implemented in `Phoole\Route\Parser\FastRouteParser` class and explained in detail in this article ["Fast request routing using regular expressions"](http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html).

    `phoole/route` uses this algorithm by default.
- **Comments on routing algorithms**

    - It does **NOT** matter that much as you may think.

        If you are using routing library in your application, different algorithms may differ only 0.1 - 0.2ms for a single request, which seems meaningless for an application unless you are using it as a standalone router.
    - Try [network routing or server routing](#issue) if you just **CRAZY ABOUT THE SPEED**.

Testing
-------

[](#testing)

```
$ composer test
```

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

[](#dependencies)

- PHP &gt;= 7.2.0

Appendix
--------

[](#appendix)

- **Routing issues**

    Base on the request informations, such as request device, source ip, request method etc., service provider may direct request to different hosts, servers, app modules or handlers.

    - *Network level routing*

        Common case, such as routing based on request's source ip, routes the request to a *NEAREST* server, this is common in content distribution network (CDN), and is done at network level.
    - *Web server routing*

        For performance reason, some of the simple routing can be done at web server level, such as using apache or ngix configs to do simple routing.

        For example, if your server goes down for maintenance, you may replace the `.htaccess` file as follows,

        ```
        DirectorySlash Off
        Options -MultiViews
        DirectoryIndex maintenance.php
        RewriteEngine On
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-l
        RewriteRule ^ maintenance.php [QSA,L]

        ```
    - *App level routing*

        It solves much more complicated issues, and much more flexible.

        Usually, routing is done at a single point `index.php`. All the requests are configured to be handled by this script first and routed to different routines.

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity10

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 93.8% 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

7

Last Release

2369d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3bae7d5f135e90fd05271574bfd04d4844169bd4c554eaa9e103e4af69267ffc?d=identicon)[phoole](/maintainers/phoole)

---

Top Contributors

[![phossa](https://avatars.githubusercontent.com/u/8499165?v=4)](https://github.com/phossa "phossa (15 commits)")[![phoole](https://avatars.githubusercontent.com/u/55728163?v=4)](https://github.com/phoole "phoole (1 commits)")

---

Tags

fast-routephoolephppsr-15psr-7routeswoolepsr-7phpmiddlewarelibrarypsr-15swooleroutefast-routephoole

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/phoole-route/health.svg)

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

###  Alternatives

[mezzio/mezzio-authentication

Authentication middleware for Mezzio and PSR-7 applications

121.6M26](/packages/mezzio-mezzio-authentication)[middlewares/fast-route

Middleware to use FastRoute

96191.1k15](/packages/middlewares-fast-route)[jimtools/jwt-auth

PSR-15 JWT Authentication middleware, A replacement for tuupola/slim-jwt-auth

20142.3k3](/packages/jimtools-jwt-auth)[segrax/open-policy-agent

Open Policy Agent client and PSR-7, PSR-15 Authorization Middleware

212.0k](/packages/segrax-open-policy-agent)

PHPackages © 2026

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