adambrett/router

This package is abandoned and no longer maintained. The author suggests using the league/route package instead.

Simple, flexible, powerful, super fast, stand-alone router

0.4 2014-02-27 19:38 UTC

README

Build Status

This router is a PHP package that implements web routing. Given a URI path and some values from $_SERVER it will execute behaviour defined by the matching route.

Your application can then continue the processing in whatever way you see fit.

Installation

Install composer in your project:

curl -s https://getcomposer.org/installer | php

Create a composer.json file in your project root:

{
    "require": {
        "adambrett/php-router": "dev-master"
    }
}

Install via composer:

php composer.phar install

Add this line to your application's index.php file:

require 'vendor/autoload.php';

Basic Usage

Hello World

Import the required classes in to your namespace:

use AdamBrett\Router\Router;
use AdamBrett\Router\UrlMatchers\Parameter as ParameterUrl;
use AdamBrett\Router\Dispatchers\Callback as CallbackDispatcher;

Instantiate a new router:

$router = new Router(
    $_SERVER['REQUEST_METHOD'],
    $_SERVER['REQUEST_URI']
);

Define a new route:

$router->get(new Route(
    new ParameterUrl('/hello/:name'),
    new CallbackDispatcher(function ($name) {
        echo "Hello, $name";
    });
));

Dispatch the application:

$router->dispatch();

Factory Router

This routing library was written to be as object oriented as possible, however there are situations where brevity would be preferable when constructing routes, and in those instances you can use the FactoryRouter.

The FactoryRouter has slightly more complicated instantiation requirements in return for far simpler route construction. Behind the scenes the FactoryRouter constructs the same UrlMatchers and Dispatchers, and uses the same Router class as you would if you were constructing the routes manually.

The FactoryRouter class has the same method signature as the Router class, but the methods take different argument types.

Import the required classes in to your namespace:

use AdamBrett\Router\Router;
use AdamBrett\Router\FactoryRouter;

Instantiate a new factory router, and pass in the normal Router object:

$router = new FactoryRouter(
    new Router($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']))
);

Define some new routes:

$router->get('/', function () {
    echo 'Hello, World';
));

$router->get('/hello/:name', function ($name) {
    echo "Hello, $name";
));

$router->get('/goodbye/:name', 'Class::method');

Dispatch the application:

$router->dispatch();

Routing Overview

This router helps you map resource URIs to custom behaviours for specific HTTP request methods (e.g. GET, POST, PUT, DELETE). The router will invoke the last route that it is passed that matches the current HTTP request URI and method.

If the router does not find routes with URIs that match the HTTP request URI and method, it will do nothing.

GET Routes

Use the router's get() method to map a route to a resource URI that is requested with the HTTP GET method.

$router = new \AdamBrett\Router\Router(
    $_SERVER['REQUEST_METHOD'],
    $_SERVER['REQUEST_URI']
);

$router->get(
    new \AdamBrett\Router\Route(
        new \AdamBrett\Router\UrlMatchers\Parameter('/recipes/:id'),
        new \AdamBrett\Router\Dispatchers\Callback(function ($id) {
            // show recipe identified by $id
        });
    )
);

In this example, an HTTP GET request for "/recipes/1" will invoke the associated callback function, passing "1" as the callback argument.

See Architecture below for more information on URL Matchers and Dispatchers.

POST Routes

Use the router's post() method to map a route to a resource URI that is requested with the HTTP POST method.

$router = new \AdamBrett\Router\Router(
    $_SERVER['REQUEST_METHOD'],
    $_SERVER['REQUEST_URI']
);

$router->post(
    new \AdamBrett\Router\Route(
        new \AdamBrett\Router\UrlMatchers\Simple('/recipes'),
        new \AdamBrett\Router\Dispatchers\Callback(function () {
            // create recipe
        });
    )
);

In this example, an HTTP POST request for "/recipes" will invoke the associated callback function.

See Architecture below for more information on URL Matchers and Dispatchers.

PUT Routes

Use the router's put() method to map a route to a resource URI that is requested with the HTTP PUT method.

$router = new \AdamBrett\Router\Router(
    $_SERVER['REQUEST_METHOD'],
    $_SERVER['REQUEST_URI']
);

$router->put(
    new \AdamBrett\Router\Route(
        new \AdamBrett\Router\UrlMatchers\Parameter('/recipes/:id'),
        new \AdamBrett\Router\Dispatchers\Callback(function ($id) {
            // update recipe identified by $id
        });
    )
);

In this example, an HTTP PUT request for "/recipes/1" will invoke the associated callback function, passing "1" as the callback argument.

See Architecture below for more information on URL Matchers and Dispatchers.

DELETE Routes

Use the router's delete() method to map a route to a resource URI that is requested with the HTTP DELETE method.

$router = new \AdamBrett\Router\Router(
    $_SERVER['REQUEST_METHOD'],
    $_SERVER['REQUEST_URI']
);

$router->delete(
    new \AdamBrett\Router\Route(
        new \AdamBrett\Router\UrlMatchers\Parameter('/recipes/:id'),
        new \AdamBrett\Router\Dispatchers\Callback(function ($id) {
            // delete recipe identified by $id
        });
    )
);

In this example, an HTTP DELETE request for "/recipes/1" will invoke the associated callback function, passing "1" as the callback argument.

See Architecture below for more information on URL Matchers and Dispatchers.

URL Matchers

Simple

new \AdamBrett\Router\UrlMatchers\Simple('/');

A simple url matcher matches on a string only. An exact match is required, and it provides no parameters in return.

RegEx

new \AdamBrett\Router\UrlMatchers\RegEx('/hello/[A-Z0-9\-]+/([A-Z]+)');

The RegEx URL Matcher allows you to use regular expressions to match URIs. Any regular expression is valid. It will be wrapped in start and end markers and is case insensitive.

Anything wrapped in () is passed to the Dispatcher as a parameter, anything not wrapped does not get treated as a parameter, but does form part of the regular expression for the match.

In the above example, given the URI /hello/to-the/world "world" would be passed to the Dispatcher as a parameter, whereas "to-the" would not.

Parameter

new \AdamBrett\Router\UrlMatchers\Parameter('/hello/:world');

The parameter matcher will match any named parameter that is an alpha-numeric character, plus underscores. It extends the RegEx URL Matcher and internally converts the named parameter to ([\\w+]) or ([A-Za-z0-9_]+).

Named parameters are just for convenience, they do not map to variable names, in all other ways the Parameter URL Matcher works just like the RegEx Url Matcher.

Dispatchers

Callback

new \AdamBrett\Router\Dispatcher\Callback(function () {
    // do stuff
});

The Callback Dispatcher is the typical micro-framework style dispatcher and works exactly the same as you're used to elsewhere.

Any parameters from your URI will be passed in to the function in the order they are received in the URI.

The callback dispatcher accepts anything that would return true for is_callable(). Typically this will be an anonymous function.

ClassMethod

With Namespace:

new \AdamBrett\Router\Dispatcher\ClassMethod('\\Namespace\\Class::method');

Without Namespace:

new \AdamBrett\Router\Dispatcher\ClassMethod('Class::method');

The ClassMethod Dispatcher can be used to instantiate a class and call a method on the resulting object. The method will be passed any parameters from the URI.

Architecture

Particular attention has been paid to making this router as flexible and extensible as possible without over complicating its use.

The Router

You start by creating a new Router. The router has a number of public methods, one for each of get, post, put, and delete, each takes exactly one parameter, an object of type Route.

A Route

A route consist of two parts, a UrlMatcher, and a Dispatcher. The route is responsible for making sure the UrlMatcher matches the URI provided to it by the router, and then taking the parameters (if any) from the UrlMatcher and passing them to the Dispatcher when the route is dispatched.

URL Matchers

A URL Matcher is responsible for testing whether or not the current URI matches the format provided to the URL Matcher by the Router, then extracting any parameters from the URI and returning them as an array when requested.

All URL Matchers should implement the UrlMatcher interface, which has only two required methods. Therefore it should be very easy to add any new ones that you require and aren't currently supported.

Dispatchers

A Dispatcher is responsible for executing some code, or simply doing something with the route parameters that the UrlMatcher extracted from the URI.

This could be executing a callback, or instantiating a class and running a method on the object.

All Dispatchers should implement the Dispatcher interface, which has only one required method. Therefore it should be very easy to add any new dispatchers that you require and aren't currently supported.

Requirements

  • PHP >=5.4

Contributing

Pull Requests

  1. Fork the php-router repository
  2. Create a new branch for each feature or improvement
  3. Send a pull request from each feature branch to the develop branch

Style Guide

This package is compliant with PSR-0, PSR-1, and PSR-2. If you notice compliance oversights, please send a patch via pull request.

Unit Tests

The library is developed using test driven development. All pull requests should be accompanied by passing unit tests with 100% coverage. phpunit is used for testing and mockery is used for mocks. faker is available as a random data generator if required.

Creating Builds

Some build tools are included via composer if required, you can run them using . ./vendor/bin/phing from the root of the project. The output will be stored in ./build and will include code coverage and code browser output. Inspect the contents of build.xml to see what's happening underneath.

Authors

Adam Brett - http://twitter.com/sixdaysad - http://adamcod.es

License

php-router is licensed under the BSD-3-Clause License - see the LICENSE file for details