PHPackages                             c9s/roller - 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. c9s/roller

ActiveLibrary

c9s/roller
==========

High performance PHP router

1.9.1(12y ago)851204BSD-3-ClausePHPPHP &gt;=5.3.0

Since Jun 4Pushed 12y ago7 watchersCompare

[ Source](https://github.com/c9s/Roller)[ Packagist](https://packagist.org/packages/c9s/roller)[ Docs](http://github.com/c9s/php-Roller)[ RSS](/packages/c9s-roller/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (3)Versions (4)Used By (0)

Roller
======

[](#roller)

PHP Roller is a simple/fast router for PHP.

Roller compiles your routes into a simple array to store routes, therefore it's fast.

Beyond that, Roller provides an extension to improve more performance for you.

[![Build Status](https://camo.githubusercontent.com/e80e2ae055362aaefb3fad8770c6145d27d9b5d622683a001dc365f935140fc9/68747470733a2f2f7365637572652e7472617669732d63692e6f72672f6339732f526f6c6c65722e706e67)](http://travis-ci.org/c9s/Roller)

FEATURES
--------

[](#features)

- Highly customizable
- Flexible
- Simple DSL (Sinatra-like syntax)
- APC cache support.
- File cache support.
- Built-in **RESTful** route generator, resource handler.
- Customizable RESTful route generator, resource handler.
- Simple, Useful route path syntax. (rails-style)
- High performance (through PHP extension, can dispatch **1607%** faster than pure php version)
- High unit test coverage, coverage &gt; **88%**.
- Ready for Frameworks.
- Annotation reader support.

Benchmark
---------

[](#benchmark)

[![](https://camo.githubusercontent.com/cdec10fdc67792f3d4c1f9180cefc4aaaf108e0d302af0283260c9adade534e1/68747470733a2f2f7261772e6769746875622e636f6d2f6339732f7068702d526f6c6c65722f6d61737465722f6d6973632f62656e63686d61726b2d636f6d70617269736f6e2e706e67)](https://camo.githubusercontent.com/cdec10fdc67792f3d4c1f9180cefc4aaaf108e0d302af0283260c9adade534e1/68747470733a2f2f7261772e6769746875622e636f6d2f6339732f7068702d526f6c6c65722f6d61737465722f6d6973632f62656e63686d61726b2d636f6d70617269736f6e2e706e67)

ROUTE CONSOLE DUMPER
--------------------

[](#route-console-dumper)

[![](https://camo.githubusercontent.com/2cf4359555cc8951115199726337eac33c96efde77642d7881fb1ec7d1366623/68747470733a2f2f7261772e6769746875622e636f6d2f6339732f7068702d526f6c6c65722f6d61737465722f6d6973632f696d67312e706e67)](https://camo.githubusercontent.com/2cf4359555cc8951115199726337eac33c96efde77642d7881fb1ec7d1366623/68747470733a2f2f7261772e6769746875622e636f6d2f6339732f7068702d526f6c6c65722f6d61737465722f6d6973632f696d67312e706e67)

INSTALL
-------

[](#install)

Install from Composer:

```
{
    "require": {
        "corneltek/roller": "~1.8"
    }
}
```

Install through PEAR:

```
pear channel-discover pear.corneltek.com
pear install corneltek/Roller

```

Or clone this repository:

```
pear install -f package.xml

```

Use thie library as a git submodule: clone this repository, pick up a PSR-0 classloader, and add `src/` to class path.

To use console dumper, you need ezc/ConsoleTools, please use PEAR installer to install:

```
pear channel-discover components.ez.no
pear install -a ezc/ConsoleTools

```

SYNOPSIS
--------

[](#synopsis)

Roller router provides a simple DSL for you to declare sinatra-like routes:

```
require 'bootstrap.php';
require 'Roller/DSL.php';

on('/path/to/:date',function() {

    return 'your content';
});

on('/path/to/:year', [ ':year' => '\d+' ] ,function() {

    return 'your content';
});

dispatch( $_SERVER['PATH_INFO'] );
```

More usage:

Initialize a router:

```
$router = new Roller\Router;
```

Add a new route with simple callback

```
$router->add( '/blog/:id/:title'  , function($id,$title) {
    return 'Blog';
});
```

Add a new route with class callback

```
$router->add( '/blog/:year/:month/:id/:title'  , array('Controller','method') );
```

Add a new route with class/action callback string:

```
$router->add( '/path/to/blog'  , 'Controller:methodName' );
```

To add a new route with requirement:

```
$router->add( '/path/to/:year' , array('Callback','method') , array(
    ':year' => '\d+',
));
```

To add a new route with requirement and closure:

```
$router->add( '/path/to/:year' , function($year) {
    return $year;
},array(
    ':year' => '\d+',
));
```

Or by `any`:

```
$router->any( '/path/to/:year' , function($year) {
    return $year;
}, array(
    ':year' => '\d+',
));
```

An alias for GET method:

```
$router->get( '/path/to/:year' , function($year) { ... } );
```

An alias for POST method:

```
$router->post( '/path/to/:year' , function($year) { ... } );
```

META ATTRIBUTE
--------------

[](#meta-attribute)

Roller currently supports: `method`, `default`, `requirement`, `post`, `get`attributes.

To add a new route with requirement and default value:

```
$router->add( '/path/to/:year' , array('Callback','method') , array(
    ':year' => '\d+',
    'default' => array(
        'year' => 2000,
    ),
));
```

To add a new route with request method (like POST method):

```
$router->add( '/path/to/:year' , array('Callback','method') , array(
    ':year' => '\d+',

    'method' => 'post',
    'default' => array(
        'year' => 2000,
    ),
));
```

RouteSet
--------

[](#routeset)

RouteSet is a route collection class, you can mount a route set to another route set.

To use RouteSet is very easy:

```
$subroutes = new Roller\RouteSet;
$subroutes->add( '/subitem' , $cb );

$routes = new Roller\RouteSet;
$routes->mount( '/item' , $subroutes );
```

Mount paths
-----------

[](#mount-paths)

To mount route set:

```
$routes = new Roller\RouteSet;
$routes->add( '/path/to/:year' , array( 'Callback', 'method' ) );

$routes = new Roller\RouteSet;
$routes->mount( '/root' , $routes );

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

Dispatch
--------

[](#dispatch)

To dispatch path:

```
$r = $router->dispatch( $_SERVER['PATH_INFO'] );
```

To evalulate response content:

```
if( $r !== false )
    echo $r();
else
    die('page not found.');
```

Customize Route Class
---------------------

[](#customize-route-class)

```
class YourRoute extends Roller\MatchedRoute
{
    // customze here.
}

$r = new Roller\Router(array(
    'route_class' => 'YourRoute'
));
$route = $r->dispatch( '/path/to/...' );    // get YourRoute object.
```

Use Annotation Reader for controllers
-------------------------------------

[](#use-annotation-reader-for-controllers)

```
class AnnotationTestController {

    /**
     * @Route("/hello/:name", name="_hello", requirements={":name" = ".+"}, vars={ "k" = 123, "b" = 234 })
     */
    function helloAction($name) {
        return $name;
    }

    /**
     * @Route("/")
     */
    function indexAction() {
        return 'index';
    }
}

$router = new Roller\Router;
$router->importAnnotationMethods( 'AnnotationTestController' , '/Action$/' );
$route = $router->dispatch('/');
$route(); // returns 'index'

$route = $router->dispatch('/hello/John');
$route();  // returns "John"
```

Cache
-----

[](#cache)

To enable apc cache:

```
$router = new Roller\Router( null , array(
    'cache_id' => '_router_testing_'
));
```

To enable file cache:

```
$router = new Roller\Router( null , array(
    'cache_id' => '_router_testing_',
    'cache_dir' => 'tests/cache',
));
```

RESTful interface
-----------------

[](#restful-interface)

Roller Router has a built-in RESTful route generator, it's pretty easy to define a bunch of RESTful routes, Roller Router also provides a simple RESTful route generator, which is pretty easy to customize your own RESTful routes.

First, initalize a RESTful plugin object:

```
$router = new Roller\Router;
$restful = new Roller\Plugin\RESTful(array(
        'prefix' => '/restful'
));
```

Add RESTful plugin to your router manager:

```
$router->addPlugin($restful);
```

To support RESTful, you have two solutions:

- `ResourceHandler`: If you need to define differnt logic for each resource, you can use `ResourceHandler`, you can separate different resource logic into different handler class.
- `GenericHandler`: If your resources use the same logic and the same permission controll, you can use `GenericHandler` for every resources.

To use ResourceHandler, register your resource id to router with your resource handler class name, each resource id is mapping to an resource handler:

```
$restful->registerResource( 'blog' , 'BlogResourceHandler' );
```

Define your resource handler, here is a simple blog example that defines how RESTful CRUD works:

```
use Roller\Plugin\RESTful\ResourceHandler;

class BlogResourceHandler extends ResourceHandler
{
    public function create()    {
        $this->codeCreated();
        return array( 'id' => 1 );
    }

    public function update($id)
    {
        $put = $this->parseInput();
        return array( 'id' => 1 );
    }

    // delete a record.
    public function delete($id)
    {
        return array( 'id' => 1 );
    }

    // load one record
    public function load($id)   { return array( 'id' => $id , 'title' => 'title' ); }

    // find records
    public function find()      {
        return array(
            array( 'id' => 0 ),
            array( 'id' => 1 ),
            array( 'id' => 2 ),
        );
    }
}
```

For the status code, see the list below:

- codeOk (200)
- codeCreated (201)
- codeAccepted (202)
- codeNoContent (204)
- codeBadRequest (400)
- codeForbidden (403)
- codeNotFound (404)

Before you dispatch URLs, router object calls the `expand` method of `ResourceHandler` class, which generates RESTful routes into the routeset of router object. And below is the generated URLs:

```
GET /restful/blog        - get blog list
GET /restful/blog/:id    - get one blog record
POST /restful/blog       - create one blog record
PUT /restful/blog/:id    - update one blog record
DELETE /restful/blog/:id - delete one blog record

```

You can override the `expand` method to define your own style RESTful URLs.

Now you should be able to dispatch RESTful urls:

```
$_SERVER['REQUEST_METHOD'] = 'get';
$r = $router->dispatch('/restful/blog/1');

// returns {"success":true,"data":{"id":"1","title":"title"},"message":"Record 1 loaded."}
$r();

$_SRVER['REQUEST_METHOD'] = 'get';
$r = $router->dispatch('/restful/blog');

// {"success":true,"data":[{"id":0},{"id":1},{"id":2}],"message":"Record find success."}
$r();
```

Customize Resource Handler
--------------------------

[](#customize-resource-handler)

Here is how RESTful route generator works:

```
    static function expand($routes, $h, $r)
    {
        $routes->add( "/$r(\.:format)" , array($h,'handleFind'),
            array(
                'get' => true ,
                'default' => array( 'format' => 'json' )
            ));

        $routes->add( '/' . $r . '(\.:format)' , array($h,'handleCreate'),
            array(
                'post' => true,
                'default' => array( 'format' => 'json' )
            ));

        $routes->add( '/' . $r . '/:id(\.:format)' , array($h,'handleLoad'),
            array(
                'get' => true,
                'default' => array( 'format' => 'json' )
            ));

        $routes->add( '/' . $r . '/:id(\.:format)' , array($h,'handleUpdate'),
            array(
                'put' => true,
                'default' => array( 'format' => 'json' )
            ));

        $routes->add( '/' . $r . '/:id(\.:format)' , array($h,'handleDelete'),
            array(
                'delete' => true,
                'default' => array( 'format' => 'json' )
            ));
    }
```

To define your own RESTful Resource Handler (Generator), you can simply inherit class from `Roller\Plugin\RESTful\ResourceHandler`:

```
use Roller\Plugin\RESTful\ResourceHandler;

class YourResourceHandler extends ResourceHandler {

    // define your own expand method
    static function expand( $routes , $handlerClass, $resourceId ) {

    }

}
```

.htaccess File for Apache
-------------------------

[](#htaccess-file-for-apache)

```
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ your_router.php/$1 [NC,L]

```

Install Extension
-----------------

[](#install-extension)

```
$ cd extension
$ phpize
$ ./configure
$ make && make install

```

Add config to your php.ini:

```
extension=roller.so
```

Hacking
-------

[](#hacking)

Run Composer Install:

```
composer install --dev

```

Install ConsoleTools:

```
pear channel-discover components.ez.no
pear install -a ezc/ConsoleTools

```

Get Onion and install it:

```
$ curl -s http://install.onionphp.org/ | bash

```

Run onion to install depedencies:

```
$ onion install

```

Now you should be able to run phpunit =)

```
$ phpunit tests

```

TODO
----

[](#todo)

- Expandable Controller (route table inside)
- Auto Expandable Controller (expand routes automatically, based on method name)

###  Health Score

32

—

LowBetter than 74% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity24

Limited adoption so far

Community14

Small or concentrated contributor base

Maturity60

Established project with proven stability

 Bus Factor1

Top contributor holds 99.7% 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 ~216 days

Total

3

Last Release

4607d ago

### Community

Maintainers

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

---

Top Contributors

[![c9s](https://avatars.githubusercontent.com/u/50894?v=4)](https://github.com/c9s "c9s (294 commits)")[![CindyLinz](https://avatars.githubusercontent.com/u/285660?v=4)](https://github.com/CindyLinz "CindyLinz (1 commits)")

### Embed Badge

![Health badge](/badges/c9s-roller/health.svg)

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

###  Alternatives

[yosimitso/workingforumbundle

A complete forum bundle

425.3k](/packages/yosimitso-workingforumbundle)[br/signed-request-bundle

Symfony2 Bundle that provides request and response signing

161.7k](/packages/br-signed-request-bundle)

PHPackages © 2026

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