v2.0.10 2018-02-12 00:17 UTC


Lightweight url router with dependency injection support.


Add the dependency to composer.json, then composer install

    "require": {
        "objectiveweb/router": "~2.0"

Basic Usage

In Objectiveweb applications, an endpoint refers to a php file which responds to url routes.

Under the hood, the route($regex, $callable) function tests $regex against the current request method and uri (e.g. "GET endpoint.php/something/([0-9]+)/?"), passing the captured parameters to $callable when matched.

Example endpoint

// include the composer autoloader

use Objectiveweb\Router;

$app = new Router();

// Routes are matched in order

$app->GET('/?', function() {
    echo "Hello index';

$app->GET('/([a-z]+)/?', function($key) {

    switch($key) {
        case 'data':
            // If the callback returns something, it's sent with status 200 (OK)
            // Arrays are automatically encoded to json
            return [ 1, 2, 3 ];
            throw new \Exception([ 'key' => $key, 'empty' => true ], 404); // respond with custom code

$app->POST('/panic', function() {
    // Exceptions are captured, message is send with the proper code
    throw new \Exception('Panic!', 500);

// catch all
$app->router("([A_Z]+) (.*), function ($method, $path) {
    return "Request matched $method and $path";


PHP classes may be bound to an url using the controller($path, $class) on public-facing endpoint (index.php)

$app->controller('/', 'ExampleController');

In this case, the request is mapped to the corresponding class method as follows


class ExampleController {

    // GET /?k=v
    function index($querystring) {
    // GET /(.*)?k=v
    function get($path1, $path2, ..., $querystring) {
    // POST /
    function post($body) {
    // Other request methods are also valid, i.e. head(), options(), etc

When a function named like the first parameter ($path[0]) exists on the controller, it gets called with the remaining parameters

// (GET|POST|PUT|...) /example/(.*)
function example($path[1], $path[2], ...) {
    // check $_SERVER['REQUEST_METHOD'] and process data

This function name may also be prefixed with the request method. In this case the query parameters are passed as the last argument

// GET /example/(.*)
function getExample($path[1], $path[2], ..., $_GET) {


// POST /example/(.*)
function postExample($path[1], $path[2], ..., $decoded_post_body) {


Other request methods are also valid (i.e. HEAD, OPTIONS, etc), check the example subdir for other uses.

Automatic routing

You can bootstrap the application on a particular namespace using


When run, the Router automatically maps the incoming requests to the given namespace. For example, a request to /products would instantiate the Namespace\ProductsController class.

If the Controller doesn't exist, the request is passed to the Namespace\HomeController. Check example/app-run.php for a working demo.

Dependency Injection

Since version 2.0, the Router extends Dice, which provides a dependency injection container to the application.

// include the composer autoloader

use Objectiveweb\Router;

$app = new Router();

// Configure the DI container rules for the PDO class
$app->addRule('PDO', [
    'shared' => true,
    'constructParams' => ['mysql:host=;dbname=mydb', 'username', 'password'] 

// From now on, you can get a configured PDO instance using
$pdo = $app->create('PDO');

When bound to paths, Controller (And dependencies of those dependencies) get automatically resolved. For example, if you define the controller


namespace MyApplication;

class MyController {

    private $pdo;
    function __construct(PDO $pdo) {
        $this->pdo = pdo;
    function index() {
        // query the database using $this->pdo

When MyApplication\MyController gets instantiated by the Router, a configured instance of PDO will be injected and reused as necessary.

You can inject dependencies adding type-hinted parameters to your controller's constructor:

function __construct(\Util\Gmaps $gmaps, \DB\ProductsRepository $products) {
  $this->gmaps = $gmaps;
  $this->products = $products;

// Use $this->gmaps and $this->products on other functions

In a another example, let's instantiate Twig

// index.php

$app = new \Objectiveweb\Router();

$app->addRule('Twig_Loader_Filesystem', array(
    'shared' => true,
    'constructParams' => [ TEMPLATE_ROOT ]

$app->addRule('Twig_Environment', array(
    'shared' => true,
    'constructParams' => [
        [ 'instance' => 'Twig_Loader_Filesystem' ],
        [ 'cache' => APP_ROOT.'/cache' ],
        [ 'auto_reload' => true ]
    'call' => [
        [ 'addGlobal', [ 'server', $_SERVER['SERVER_NAME'] ] ],
        [ 'addGlobal', [ 'app_name', APP_NAME ] ],
        [ 'addGlobal', [ 'session', $_SESSION ] ],
        [ 'addFunction', [ new Twig_SimpleFunction('url', function ($path) {
            return \Objectiveweb\Router::url($path);

$app->controller('/', 'MyController')

Then, inject it on your controller's constructor

class MyController {

    private $twig;
    private $pdo;
    function __construct(Twig_Environment $twig, PDO $pdo) {
        $this->twig = $twig;
        $this->pdo = $pdo;
    function index() {
        return $this->twig->render(...);

You can also fetch the twig reference using

$twig = $app->create('Twig_Environment');


Dice Rules can be configured with these properties:

  • shared (boolean) - Whether a single instance is used throughout the container. View Example
  • inherit (boolean) - Whether the rule will also apply to subclasses (defaults to true). View Example
  • constructParams (array) - Additional parameters passed to the constructor. View Example
  • substitutions (array) - key->value substitutions for dependencies. View Example
  • call (multidimensional array) - A list of methods and their arguments which will be called after the object has been constructed. View Example
  • instanceOf (string) - The name of the class to initiate. Used when the class name is not passed to $app->addRule(). View Example
  • shareInstances (array) - A list of class names that will be shared throughout a single object tree. View Example