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

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

pagemill/router
===============

A PHP request router

v3.0.0(8mo ago)017.3k↓23.1%3BSD-3-ClausePHPPHP ^8.2

Since Jun 2Pushed 8mo ago9 watchersCompare

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

READMEChangelog (7)Dependencies (3)Versions (11)Used By (3)

PageMill Router
===============

[](#pagemill-router)

This library determines a route for a web request. It is built to be easy to use and fast.

Basic Routing
-------------

[](#basic-routing)

For the most basic of routing needs, an array can simply be passed to the Router class constructor. Each route array should consist of a `type`, `pattern`, and either an `action` or array of sub-routes called `routes`. While `action` has no meaning to the router itself, its purpose is for use after matching.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "exact",
            "pattern" => "/foo",
            "action" => "Foo"
        ],
        [
            "type" => "exact",
            "pattern" => "/foo/bar",
            "action" => "FooBar"
        ],
    ]
);

$route = $r->match("/foo");
```

Adding with Methods
-------------------

[](#adding-with-methods)

You can also add routes using the `add` method.

```
$r = new PageMill\Router\Router();
$r->add("exact", "/foo", "Foo");
$r->add("exact", "/foo/bar/", "FooBar");
$route = $r->match("/foo");
```

If performance is important, it is suggested to pass the routes into the constructor.

Match Types
-----------

[](#match-types)

There are three matching types supported plus a default route.

**exact** - The request path must match `pattern` exactly.

**starts\_with** - Matches when the request path begins with the exact value of `pattern`.

**regex** - Uses a regular expression to match against the reqeust path.

**default** - A default route to use if no other route is matched. A default route does not require a `pattern`. There must only be one default route defined.

Matching Tokens
---------------

[](#matching-tokens)

Optionally, a route can include an array of tokens that allow for using values from the request path to fill a named array in the return value of the `match`method. This is only valid for `starts_with` and `exact` match types.

For `starts_with` matches, the tokens will be filled in based on values that appear in the request path between slashes (`/`) that are not part of the pattern.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "starts_with",
            "pattern" => "/foo/",
            "action" => "Foo",
            "tokens" = [
                "group",
                "id"
            ]
        ]
    ]
);

$route = $r->match("/foo/1/2/");
```

The value of `$route` would be:

```
array(
    "type" => "starts_with",
    "pattern" => "/foo/",
    "action" => "Foo",
    "tokens" = [
        "group" => 1,
        "id" => 2
    ]
)
```

For `regex` matches, the tokens will be filled based on back references used in the regular expression.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "regex",
            "pattern" => "/foo/(\d+)/(\d+)/",
            "action" => "Foo",
            "tokens" = [
                "group",
                "id"
            ]
        ]
    ]
);

$route = $r->match("/foo/1/2/");
```

The value of `$route` would be:

```
[
    "type" => "regex",
    "pattern" => "/foo/",
    "action" => "Foo",
    "tokens" = [
        "group" => 1,
        "id" => 2
    ]
]
```

Matching Hostname, Request Method, Accept header, and Other HTTP Headers
------------------------------------------------------------------------

[](#matching-hostname-request-method-accept-header-and-other-http-headers)

It is also possible to match on hostname, request method, Accept header, and other HTTP headers by adding these settings to the route array.

`host` - Matches the HTTP Host header. `method` - Matches the HTTP request method (GET, POST, etc.) `accept` - Validates the Accept header contains one of a list of mime types. `headers` - An array of headers and the patterns to match them.

To match on hostname, add `host` to the route config. To only match `GET`requests, add `method`.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "regex",
            "pattern" => "/foo/(\d+)/(\d+)/",
            "action" => "Foo",
            "host" => "www.example.com",
            "method" => "GET"
        ]
    ]
);
$route = $r->match("/foo/1/2/");
```

The value of `$route` would be:

```
[
    "type" => "starts_with",
    "pattern" => "/foo/",
    "action" => "Foo",
    "tokens" = [
        "group" => 1,
        "id" => 2
    ]
    "host" => "www.example.com",
    "method" => "GET"
]
```

By default, this is treated as an exact match. You can do more complex matching by providing an array with `type` and `pattern` set. This is true of `host`, `method` and the patterns in the `headers` array.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "regex",
            "pattern" => "/foo/(\d+)/(\d+)/",
            "action" => "Foo",
            "host" => [
                "type" => "regex",
                "pattern" => '/\.example\.com$/'
            ],
            "method" => "GET"
        ]
    ]
);
$route = $r->match("/foo/1/2/");
```

The matched values of these settings will be returned in the matched route array. The value of `$route` would be:

```
[
    "type" => "starts_with",
    "pattern" => "/foo/",
    "action" => "Foo",
    "tokens" = [
        "group" => 1,
        "id" => 2
    ]
    "host" => "www.example.com",
    "method" => "GET"
]
```

To validate the Accept header against a list of mime types, this route config could be used. For this example, assume the Accept header from the client contains `text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`.

NOTE: Unlike other options, the `accept` option only accepts a single string mime type or an array of mime types.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "regex",
            "pattern" => "/foo/(\d+)/(\d+)/",
            "action" => "Foo",
            "accept" => [
                "text/html"
            ]
        ]
    ]
);
$route = $r->match("/foo/1/2/");
```

The value of `$route` would be:

```
[
    "type" => "starts_with",
    "pattern" => "/foo/",
    "action" => "Foo",
    "tokens" = [
        "group" => 1,
        "id" => 2
    ]
    "accept" => "text/html"
]
```

Router will honor the clients quality scores from the Accept header. For an explination of the quality score used in HTTP client Accept headers, see . If the quality scores for the matching mime types is equal, the order they are defined in the configuration will be honored.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "regex",
            "pattern" => "/foo/(\d+)/(\d+)/",
            "action" => "Foo",
            "accept" => [
                "application/json"
                "text/html"
            ]
        ]
    ]
);
$route = $r->match("/foo/1/2/");
```

Because the quality score for text/html is not defined in the Accept header, it is assumed to be 1. The value of `$route` would be:

```
[
    "type" => "starts_with",
    "pattern" => "/foo/",
    "action" => "Foo",
    "tokens" = [
        "group" => 1,
        "id" => 2
    ]
    "accept" => "text/html"
]
```

To match an arbitrary HTTP header, add `headers` to the route config.

This example will ensure that the `Authorization` header contains `12345678`.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "regex",
            "pattern" => "/foo/(\d+)/(\d+)/",
            "action" => "Foo",
            "headers" => [
                "Authorization" => [
                    "type" => "exact",
                    "pattern" => '12345678'
                ]
            ]
        ]
    ]
);
$route = $r->match("/foo/1/2/");
```

The value of `$route` would be:

```
[
    "type" => "starts_with",
    "pattern" => "/foo/",
    "action" => "Foo",
    "tokens" = [
        "group" => 1,
        "id" => 2
    ]
    "headers" => [
        "Authorization" => "12345678"
    ]
]
```

Default Route
-------------

[](#default-route)

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "exact",
            "pattern" => "/foo/",
            "action" => "Foo",
        ],
        [
            "type" => "default",
            "action" => "Default",
        ]
    ]
);
$route = $r->match("/foo/1/2/");
```

The value of `$route` would be:

```
[
    "type" => "default",
    "action" => "Default",
]
```

Note: No tokens will be returned and no pattern matching is performed on the path for the default route.

Only one default route is allowed. An `InvalidRoute` exception will be thrown if more than one default route is defined.

Adding Sub Routes (aka Route Maps)
----------------------------------

[](#adding-sub-routes-aka-route-maps)

If you have several routes that all have the same prefix or match the same pattern, it can be beneficial to group those routes as sub-routes under a more general route. For example, if we have multiple routes that fall under the `/foo` path, we could configure our routes like this:

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "starts_with",
            "pattern" => "/foo",
            "routes" => [
                [
                    "type" => "exact",
                    "pattern" => "/foo/bar",
                    "action" => "FooBar"
                ],
                [
                    "type" => "exact",
                    "pattern" => "/foo/baz",
                    "action" => "FooBaz"
                ],
            ]
        ]
    ]
);
$route = $r->match("/foo/bar");
```

The value of `$route` would be:

```
[
    "type" => "exact",
    "pattern" => "/foo/bar",
    "action" => "FooBar"
]
```

Saving the Route List
---------------------

[](#saving-the-route-list)

If you would like to save the route list for reuse, you can call the `getRoutes()` method.

```
$r = new PageMill\Router\Router(
    [
        [
            "type" => "exact",
            "pattern" => "/foo/",
            "action" => "Foo",
        ],
        [
            "type" => "default",
            "action" => "Default",
        ]
    ]
);
$routes = $r->get_routes();
```

###  Health Score

50

—

FairBetter than 96% of packages

Maintenance61

Regular maintenance activity

Popularity26

Limited adoption so far

Community17

Small or concentrated contributor base

Maturity82

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

Recently: every ~560 days

Total

8

Last Release

248d ago

Major Versions

0.1 → 1.0.02017-09-18

v1.1.0 → v2.0.02020-03-22

v2.0.2 → v3.0.02025-09-12

PHP version history (5 changes)0.1PHP &gt;=5.5.0

1.0.0PHP &gt;=7.0

v2.0.0PHP ~7.3

v2.0.2PHP ^7.4 || ^8.0

v3.0.0PHP ^8.2

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/49531?v=4)[Brian Moon](/maintainers/brianlmoon)[@brianlmoon](https://github.com/brianlmoon)

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

---

Top Contributors

[![brianlmoon](https://avatars.githubusercontent.com/u/49531?v=4)](https://github.com/brianlmoon "brianlmoon (48 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

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

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

###  Alternatives

[friendsofsymfony/rest-bundle

This Bundle provides various tools to rapidly develop RESTful API's with Symfony

2.8k73.3M319](/packages/friendsofsymfony-rest-bundle)[php-http/discovery

Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations

1.3k309.5M1.2k](/packages/php-http-discovery)[pusher/pusher-php-server

Library for interacting with the Pusher REST API

1.5k94.8M293](/packages/pusher-pusher-php-server)[react/http

Event-driven, streaming HTTP client and server implementation for ReactPHP

78026.4M414](/packages/react-http)[php-http/curl-client

PSR-18 and HTTPlug Async client with cURL

48347.0M384](/packages/php-http-curl-client)[smi2/phpclickhouse

PHP ClickHouse Client

84310.1M71](/packages/smi2-phpclickhouse)

PHPackages © 2026

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