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

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

proteins/route
==============

A simple and fast URL router

1.1.0(6y ago)044MITPHPPHP ^7.2

Since May 28Pushed 6y ago1 watchersCompare

[ Source](https://github.com/php-protein/route)[ Packagist](https://packagist.org/packages/proteins/route)[ RSS](/packages/proteins-route/feed)WikiDiscussions master Synced 2mo ago

READMEChangelog (4)Dependencies (7)Versions (11)Used By (0)

[![](https://raw.githubusercontent.com/php-protein/docs/master/assets/protein-large.png)](https://raw.githubusercontent.com/php-protein/docs/master/assets/protein-large.png)

Protein | Route
===============

[](#protein--route)

A simple and fast URL router
----------------------------

[](#a-simple-and-fast-url-router)

### Install

[](#install)

---

```
composer require proteins/route

```

Require the global class via :

```
use Proteins\Route;
```

### URL mapping

[](#url-mapping)

---

You can define a route via the `on` method.

```
Route::on('/hello',function(){
   echo 'Hello, Friend!';
});
```

This is the simplest form to define an `HTTP GET` route responding on URL `/hello`.
You can map the same route to multiple request methods using the fluent api interface.

```
Route::on('/hello')
  ->via('get','post')
  ->with(function(){
     echo 'Hello, Friend!';
  });
```

The `via` method accepts an array of string for handled HTTP request methods.

The `with` method binds a callable function to the route.

If you need to map various HTTP methods to different callbacks for a single URL *(like exposing a resource via a REST API)* the `map` method allows you to pass a `method` =&gt; `callback` dictionary.

```
Route::map('/entity(/:id)/?',[
    'get' => function($id=null){
		// READ: fetch the $id element or all if $id === null
    },
    'post' => function($id=null){
    	// CREATE: build a new element
    },
    'put' => function($id=null){
    	// UPDATE: modify $id element's properties
    },
    'delete' => function($id=null){
    	// DELETE: delete $id element
    },
])
```

The `any` shorthand will trigger the route responding on URL `/hello` for any HTTP verb.

```
Route::any('/hello',function(){
   echo 'Hello, World!';
});
```

This is the same as doing :

```
Route::on('/hello')
  ->via('*')
  ->with(function(){
     echo 'Hello, World!';
  });
```

### URL pattern matching and parameters extraction

[](#url-pattern-matching-and-parameters-extraction)

---

The route pattern is essentially a Regular Expression with some slight differencies.

The pattern is **ALWAYS** matched against the **end** of the `REQUEST_URI` parameter (stripped of the query string).

**Rules:**

- every `(...)` group becomes optional
- you can extract parameters via `:named_parameter`
- the pattern can't contain the `#` character

**Examples:**

```
Route::on('/element(/:id)/?',function($id=null){
	if (null === $id){
		$result = get_all_elements();
	} else {
		$result = get_element_by_id($id);
	}
	print_r($result);
});
```

In this example the optional (is in a `(...)` group) `:id` is extracted when present, and the route can be optionally terminated by a `/`.

This route handles all of these request:

- `/element`
- `/element/`
- `/element/123`
- `/element/123/`
- `/element/1919191`
- `/element/462635`
- etc..

But, as you can see, this example handles also `/element/fooo`. If we want to give format rules to an extracted parameters we can use the `rules` method.

The `rules` method accepts a `named_parameter` =&gt; `regex` dictionary.

`rules([ 'parameter_name' => 'parameter_regex_pattern' ])`

We can strenghten the former example adding rules to the `id` parameter for accepting only integer values *(defined by the \\d+ regex pattern)*.

**Example:**

```
Route::on('/element(/:id)/?',function($id=null){
	if (null === $id){
		$result = get_all_elements();
	} else {
		$result = get_element_by_id($id);
	}
	print_r($result);
})
->rules([ 'id' => '\d+' ]);
```

### Route groups

[](#route-groups)

---

You can encapsulate routes based on a prefix pattern. If the current request doesn't match the group URL pattern, relative routes definition are **not** registered.

> **Note:** This behaviour is controlled by the `core.route.pruning` flag.

This feature can be used for response-time optimization and for mounting route trees to a dynamic URL prefix.

You can define multiple *nested route groups*.

**Examples:**

**Admin section**

```
Route::group('/admin',function(){

    Route::on('/',function(){
        echo "Admin Index";
    });

    Route::on('/login')
    ->via('get','post')
    ->with(function(){
        // Handle login
    });

    Route::on('/logout',function(){
       // handle logout
    });

    Route::group('/dashboard',function(){

      Route::on('/',function(){
         // Dashboard
      });

      Route::on('/details',function(){
         // Dashboard Details
      });

    });

});
```

**Route groups with dynamic parameters**

RouteGroups can have dynamic parameters that will be extracted like normal Routes.

```
Route::group("/book/:id", function($id){
  $book = new Book($id);

  Route::on("/", function() use ($book){
    return $book;
  });

  Route::on("/:field", function($field) use ($book){
    return $book->$field;
  });

});
```

### Route middlewares

[](#route-middlewares)

---

You can append a list of middlewares `before` and `after` a Route, or a RouteGroup.

> If a middleware returns `false` the entire route execution halts.

Middlewares can be chained, the `before`s will be executed in *reverse declaration order* (FIFO), the `after`s in *direct declaration order* (LIFO).

```
Route::on('/',
	"[TEST]"
)
->before(function(){
    echo "(B1)";
})
->before(function(){
    echo "(B2)";
})
->after(function(){
    echo "(A1)";
})
->after(function(){
    echo "(A2)";
});
```

Gives this output :

```
(B2)(B1)[TEST](A1)(A2)

```

You can apply a middleware to multiple routes a single time using a RouteGroup :

```
Route::group('/private',function(){

    Route::on('/', ... );
    Route::on('/dashboard', ... );
    Route::on('/profile', ... );
    Route::on('/settings', ... );

})->before(function(){
    if ( ! user_authorized() ) {
        Response::error(403,"Forbidden");
        return false;
    }
});
```

### Dispatching routes

[](#dispatching-routes)

---

Remember to invoke the `dispatch` method before script end for route execution.

```
Route::on('/hello',function(){
   echo 'Hello, Friend!';
});

// Run the route dispatcher.
Route::dispatch();
```

You can override the request URI and method passing them as parameters to the dispatch method :

```
Route::dispatch($URL=null, $method=null, $return_route=false)
```

Example :

```
Route::dispatch('/my/forced/uri','OPTIONS');
```

The matched (if any) route can be returned without being automatically executed passing true to the `return_route` parameter :

```
$matched_route = Route::dispatch(null,null,true);
```

### Route can't find a match. (HTTP 404)

[](#route-cant-find-a-match-http-404)

---

When no routes matches the current request, the `404` event is triggered.

You can append a view to the `Response` to show a courtesy page.

```
Event::on(404,function(){
  Response::html( View::from('errors/404') );
});
```

### Render shortcuts

[](#render-shortcuts)

---

Instead of the rendering callback, you can also pass a string or a view, for direct rendering.

**Closure**

```
Route::on('/',function(){
  return View::from('index');
});
```

```
I'm the index!

```

**A `View`**

```
Route::on('/', View::from('index') );
```

```
I'm the index!

```

**A string *(not a callable one)***

```
Route::on('/', 'Not a callable string' );
```

```
Not a callable string

```

**An object**

```
Route::on('/',(object)[
  'alpha' => 123,
  'beta'  => [1,2,3]
]);
```

```
{"alpha":123,"beta":[1,2,3]}

```

### HTTP/2 Resource Push

[](#http2-resource-push)

---

You can push resources directly from the Route and RouteGroup definitions.
The syntax is the same as for the `Response::push` [method](/caffeina-core/core/wiki/Response#http2-server-push).

```
Route::on('/', function() {
  return View::from('index');
})->push([
  'style'  => '/assets/css/main.css',
  'script' => [
    '/assets/js/vendors.js',
    '/assets/js/main.js',
  ],
]);
```

### URL tagging and Reverse Routing

[](#url-tagging-and-reverse-routing)

---

You can add a name tag to a route via the `tag` method :

```
Route::on('/user/:id', function ($id) {
  return "USER[$id]";
})->tag('user');
```

A named route is retrieved via the `Route::tagged($name)` method :

```
$user_route = Route::tagged('user');
```

To get the URL for a route use the `getURL($params = [])` method :

```
echo $user_route->getURL();
```

As a shorthand, you can obtain the URL for the named route via the `Route::URL($name, $params = [])` helper :

```
echo Route::URL('user');
```

```
/user

```

You can also pass an array to map and assign the dynamic values of the route.

```
echo Route::URL('user',[
  'id' => 123,
]);
```

```
/user/123

```

> **Note:** The returned value of the `Route::URL` method is an \[\[URL\]\] object.

### Events and Filters

[](#events-and-filters)

---

Route has the Events trait behaviour, the only difference is that the `Events::on` method is renamed to `onEvent` to avoid collisions with the `Route::on` handler.

```
Route::onEvent('start',function($route, $args, $method){
   echo "Called route.\n";
});
```

#### Available Events

[](#available-events)

NameParametersDescription`start``route`,`args`,`method`A route run method has been called.`before``route`,`middleware`A route pre middleware is called.`after``route`,`middleware`A route post middleware is called.`end``route`,`args`,`method`A route run method has ended.`404`No routes can be dispatched.#### Available Filters

[](#available-filters)

NameParametersDescription`core.route.response``response_body`Filter the route response body output.

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity8

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity60

Established project with proven stability

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

Total

10

Last Release

2543d ago

### Community

Maintainers

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

---

Top Contributors

[![lastguest](https://avatars.githubusercontent.com/u/178900?v=4)](https://github.com/lastguest "lastguest (10 commits)")

### Embed Badge

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

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

###  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)[nyholm/psr7

A fast PHP7 implementation of PSR-7

1.3k235.4M2.4k](/packages/nyholm-psr7)[pusher/pusher-php-server

Library for interacting with the Pusher REST API

1.5k94.8M293](/packages/pusher-pusher-php-server)[spatie/crawler

Crawl all internal links found on a website

2.8k16.3M52](/packages/spatie-crawler)[react/http

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

78126.4M414](/packages/react-http)

PHPackages © 2026

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