Routing

API Documentation

Build Coverage

Routing Library documentation

The Routing library makes it possible to route a URL to a particular method or closure, with named routes.

The router is responsible for handling the various routes of an application, created in a route collection.

use Framework\Routing\Collection;
use Framework\Routing\Router;

$router = new Router();

// Defines a collection of routes for the Origin "http://domain.tld"
$router->serve('http://domain.tld', static function (Collection $routes) {
    // Route the "/" path to App\Controllers\Home::index method on GET requests
    $routes->get('/', 'App\Controllers\Home::index');
    // Route the "/contact" path to App\Controllers\Contact::index method on GET requests
    $routes->get('/contact', 'App\Controllers\Contact::index');
    // Route the "/contact" path to App\Controllers\Contact::create method on POST requests
    $routes->post('/contact', 'App\Controllers\Contact::create');
});

// Match the current Route
$route = $router->match($_SERVER['REQUEST_METHOD'], $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
// Run the route. Call the method or closure
$route->run();

Collection

The collection has several methods for creating routes.

Most receive the name of the HTTP method to which the route is assigned.

For example, the HTTP GET method has the get method. The POST, post, etc.

// Named route "home"
$routes->get('/', 'App\Controllers\Home::index', 'home');
// Route with Closure instead of method in class
$routes->get('/test', static function () {
    return 'Hello world!';
}, 'test');
// Different HTTP Methods using placeholders
$routes->get('/user', 'App\Users::index');
$routes->post('/user', 'App\Users::create');
$routes->get('/user/{int}', 'App\Users::show/0');
$routes->patch('/user/{int}', 'App\Users::update/0');
$routes->put('/user/{int}', 'App\Users::replace/0');
$routes->delete('/user/{int}', 'App\Users::delete/0');

Placeholders

A path can take placeholders to make it dynamic. So that /users/1 is within /users/{int}.

The available placeholders are:

Placeholder Utility
{alpha} Accepts alphabetic characters
{alphanum} Accepts alphanumeric characters
{any} Accepts any characters
{hex} Accepts a hexadecimal string
{int} Accepts valid integers in PHP
{md5} Accept a md5 hash
{num} Accept numbers
{port} Accepts valid port number
{scheme} Accepts HTTP or HTTPS schema
{segment} Accepts a segment of a URL path
{subdomain} Accepts a subdomain
{title} Accepts title format

Resources

To quickly create an API resource, you can do this:

$routes->resource('/users', 'App\Users', 'users');

Which will create 6 routes.

HTTP Method Path PHP Method Name
GET /users App\Users::index users.index
POST /users App\Users::create users.create
GET /users/{int} App\Users::show/0 users.show
PATCH /users/{int} App\Users::update/0 users.update
PUT /users/{int} App\Users::replace/0 users.replace
DELETE /users/{int} App\Users::delete/0 users.delete

If you want to make web pages available to manipulate the resource, you can create a web resource. Which will create the previous 6 routes plus 4 web routes:

$routes->webResource('/users', 'App\Users', 'users');
HTTP Method Path PHP Method Name
GET /users/new App\Users::new users.web_new
GET /users/{int}/edit App\Users::edit/0 users.web_edit
POST /users/{int}/delete App\Users::delete/0 users.web_delete
POST /users/{int}/update App\Users::update/0 users.web_update

Groups

Sometimes the route path can become repetitive and to simplify route creation you can group them by URL path.

$routes->group('/blog',[
    // Route for "/blog/"
    $routes->get('/','App\Blog\Posts::index'),
    // Rout for "/blog/{title}"
    $routes->get('/{title}','App\Blog\Posts::show/0'),
]);

Grouping works on multiple layers. This also works:

$routes->group('/blog',[
    // Route for "/blog/"
    $routes->get('/','App\Blog\Posts::index'),
    $routes->group('/posts',[
        // Route for "/blog/posts/"
        $routes->get('/','App\Blog\Posts::index'),
        // Route for "/blog/posts/{title}"
        $routes->get('/{title}','App\Blog\Posts::show/0'),
    ])
]);

Namespaces

The namespace of some routes may become repetitive to type. For simplicity, you can use the namespace:

$routes->namespace('App\Controllers',[
    // App\Controllers\Users::index
    $routes->get('/user', 'Users::index'),
    $routes->post('/user', 'Users::create'),
    $routes->get('/user/{int}', 'Users::show/0'),
    $routes->patch('/user/{int}', 'Users::update/0'),
    $routes->put('/user/{int}', 'Users::replace/0'),
    $routes->delete('/user/{int}', 'Users::delete/0'),
    $routes->group('/posts',[
        $routes->get('/','Blog\Posts::index'),
        // App\Controllers\Blog\Posts::show/0
        $routes->get('/{title}','Blog\Posts::show/0'),
    ])
]);

Route Not Found

Each collection can have its own custom Error 404 page. Just set the path to the controller class or a closure.

$routes->notFound(static function () {
    return '<h1>Error 404</h1>';
});
// or
$routes->notFound('App\Controllers\Errors::notFound');

Router

The router is where several collections are stored, and it is decided which route will be executed according to the HTTP method and request URL.

$router->serve('http://domain.tld', static function (Collection $routes) {
    // Routes ...
});
$router->serve('http://other.xyz', static function (Collection $routes) {
    // Routes ...
});

Error 404

If a collection does not have an Error 404 route set, the default router page will be responded. You can also customize it:

$router->setDefaultRouteNotFound('App\Errors::notFound');

Named Routes

Routes in a collection can be named for easy route maintenance when a URL changes its path.

Through the Router you can take routes by name:

$route = $router->getNamedRoute('home');

Matched Route

After calling the match method, you can get the route with getMatchedRoute:

$route = $router->getMatchedRoute();

HTTP OPTIONS Method

The HTTP OPTIONS method serves to show which methods a particular resource makes available. With the routes defined, the server can answer automatically which methods are allowed.

$router->setAutoOptions(true);