2017 © Pedro Peláez
 

library router

HTTP router

image

dc/router

HTTP router

  • Tuesday, December 13, 2016
  • by vegardlarsen
  • Repository
  • 2 Watchers
  • 1 Stars
  • 115 Installations
  • PHP
  • 3 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 5 Versions
  • 0 % Grown

The README.md

DC\Router - Easy HTTP routing, (*1)

Installation

$ composer install dc/router

Or add it to composer.json:, (*2)

"require": {
    "dc/router": "0.*",
    "dc/ioc": "0.*"
}
$ composer install

This package has a suggests dc/ioc, but it really is a very strong recommendation. It will be painful to use without it., (*3)

Build status, (*4)

Getting started

We strongly recommend you use this with the dc/ioc package, which we use in all our samples for easy setup. This makes it easy to set up:, (*5)

<?php
$container = new \DC\IoC\Container();

$container->registerModules([
    new \DC\Router\IoC\Module(['\Fully\Qualified\ControllerName', '\CatsController']),
    new \DC\Cache\Module(),
    new \DC\JSON\IoC\Module()
]);

$router = $container->resolve('\DC\Router\Router');
$router->route($container->resolve('\DC\Router\IRequest'));

DC\Router is based around routes and controllers. A route is a single function that gets invoked when a URL is hit. A controller is a class containing one or more routes that can be invoked if its URL is matched. Here is an example:, (*6)

class CatsController extends \DC\Router\ControllerBase {
    /**
     * @route GET /cats
     */
    function list() {
        return "<h1>many cats here</h1>";
    }
}

The magic happens because of two steps:, (*7)

  1. You are inheriting from ControllerBase, which implements IController for you.
  2. You have decorated the list method with a @route PhpDoc comment to specify which path this matches.

Routes

The special @route PHPDoc comment specifies which URLs match the route. They support variables:, (*8)

/**
 * @route GET /cats/{id:int}
 */ 
function getById($id) {
  // $id will be an int here
}

/**
 * @route GET /cats/{name}
 */
function getByName($name) {
  // $name will be a string (we didn't have to specify string as it is the default)
}

/**
 * @route GET /cats/{catName}/toys/{toyId:int}
 */
function getToy($toyId, $catName) {
  // notice that the variables for the method do not need to be in the same order as in the route,
  // but they need to have the same names
}

/**
 * @route GET /cats/?filter={cats:catFilter}
 */
function filterCats($cats, $filter) {
  // This uses the catFilter parameter type (see below) to convert the input sent through the 
  // filter GET parameter and provides it with the variable named $cats. The ONLY time you'll 
  // use this, is if you want parameter type conversion, or when you want to rename the query 
  // parameter before it arrives. Note that the $filter parameter is still available, but is 
  // a string 
}

Parameter types

You can register your own parameter types. By simply implementing IParameterType you can easily convert a input parameter from a URL into a full-fledged object:, (*9)

class CatParameterType implements \DC\Router\IParameterType {
  private $catService;  
  function __construct(\ICatService $catService) {
    $this->catService = $catService;
  }
  function getType() { return "cat"; }
  function getRegularExpression() { return "\d+"; }
  function transformValue($id) {
    return $this->catService->get($id);
  }
}

You'll need to register this with your IoC container before the routing system is created:, (*10)

$container = new \DC\IoC\Container();

$container->registerModules([
    new \DC\Router\IoC\Module(['\CatsController']),
    new \DC\Cache\Module(),
    new \DC\JSON\IoC\Module()
]);

$container->register('\UserParameterType')->to('\DC\Router\IParameterType')->withContainerLifetime();

$router = $container->resolve('\DC\Router\Router');
$router->route($container->resolve('\DC\Router\IRequest'));

Now you can use it in your own routes:, (*11)

/**
 * @route GET /cat/{catObject:cat}
 */
function getCatById(\Cat $catObject) {
  var_dump($catObject);
} 

Dependency injection

If you use the setup above, controllers are injected when instantiated, so you can easily specify dependencies:, (*12)

class CatsController extends \DC\Router\ControllerBase {
  /**
   * @param \ICatToy[] $catToys A list of the toys you have for your cats
   */
  function __construct(\CatService $catsService, array $catToys) {
     // store your catsService and your toys
  }
}

API controllers

If you want to make a JSON API, inherit from \DC\Router\JsonController instead. Anything you return will automatically be serialized to JSON before being sent to the client., (*13)

These API controllers can also receive posted JSON data, provided the Content-Type header is set correctly. To access the posted data in a route, use the getRequestBodyAsObject() method:, (*14)

class CatsController extends \DC\Router\JsonController {
  /**
   * @route POST /cat
   */
  function new() {
     $cat = $this->getRequestBodyAsObject();
     return $cat;
  }
}

The Versions