Skip to main content
Github

Routing

Learn how to create routes with pattern-based matching for closures, functions, methods, and controllers, and how to isolate routes within distinct scopes.

To create a new route, edit the system/main.php file. If you want the route to be available only in development mode, edit the system/dev.php file instead.

Create routes

Creating a route should be done using:

$app->action(array | string $methods, string $path, $callback);

Using anonymous function (closure)

$app->action('GET', '/closure', function () { return 'Hello "closure"!'; });

Using functions with a specified name

function sample() { echo 'Hour server: ', date('h:i:s'); } $app->action('GET', '/hour', 'sample');

Using the method of an instance

class Sample { public function method() { echo 'Hello!'; } } $instance = new Sample(); $app->action('ANY', '/', [$instance, 'method']);

Using routes with multiple HTTP methods

$app->action(['GET', 'HEAD', 'POST'], '/foo', function () { ... }); $app->action(['PATCH', 'PUT'], '/bar', function () { ... });

Using Controllers

To better understand this in practice, create a file at system/Controllers/Blog/Post.php with the following contents:

<?php namespace Controllers\Blog; class Post { public function list($app) { return 'Coming soon'; } public function read($app, $params) { $id = $params['id']; return "ID: {$id}"; } }

Then create the routes (don't need to include the Controllers namespace prefix — the framework automatically prepends it), example:

$app->action('GET', '/blog/posts', 'Blog\Home::list'); $app->action('GET', '/blog/posts/<id>', 'Blog\Home::post');

Grouping routes (scope)

The route grouping (scope) system is simple and flexible. It is based on the full URL or path and supports the * wildcard, as well as the same patterns available for routes. A example of routes will only be added if the path starts with /blog/:

/* * http://localhost:5000/blog/ * http://localhost:5000/blog/post * http://localhost:5000/blog/search */ $app->scope('/blog/', function ($app, $params) { $app->action('GET', '/', function () { ... }); $app->action('POST', '/post', function () { ... }); $app->action('GET', '/search', function () { ... }); });

Restricting routes to a scope that only accepts HTTPS or HTTP

Routes will only be added if you are accessing via HTTPS:

$app->scope('https://*', function ($app, $params) { ... });

Routes will only be added if you are accessing via HTTP:

$app->scope('http://*', function ($app, $params) { ... });

Restricting routes to be accessible only within a specific domain

Routes will only be added when the request host is example.com

$app->scope('*://example.com/', function ($app, $params) { ... });

Restricting routes to a scope by subdomain

Routes will only be added if you are accessing a subdomain of example.com, e.g., site1.example.com

$app->scope('*://*.example.com/', function ($app, $params) { ... });

Using a pattern to capture the subdomain:

$app->scope('*://<subdomain>.example.com/', function ($app, $params) { $subdomain = $params['subdomain']; ... });

Route and scopes with URL patterns

Using a pattern that expects a path with an id of any format:

$app->action('GET', '/users/<id>/<user>', function ($app, $params) { $id = $params['id']; $username = $params['user']; ... });

Using a pattern that expects a path with an id in UUID format:

$app->action('GET', '/users/<id:uuid>/<user>', function ($app, $params) { $id = $params['id']; $username = $params['user']; ... });

Standard patterns:

Type Example Description
alnum $app->action('GET', '/baz/<video:alnum>', ...); Accepts only alphanumeric parameters; $params returns ['video' => ...]
alpha $app->action('GET', '/foo/bar/<name:alpha>', ...); Accepts only alphabetic parameters; $params returns ['name' => ...]
decimal $app->action('GET', '/baz/<price:decimal>', ...); Accepts only decimal number parameters; $params returns ['price' => ...]
num $app->action('GET', '/foo/<id:num>', ...); Accepts only integer parameters; $params returns ['id' => ...]
nospace $app->action('GET', '/foo/<nospace:nospace>', ...); Accepts any characters except spaces, such as %20 or tabs (see the \S regex pattern)
uuid $app->action('GET', '/bar/<barcode:uuid>', ...); Accepts UUID-formatted parameters; $params returns ['barcode' => ...]
version $app->action('GET', '/baz/<api:version>', ...); Accepts parameters in Semantic Versioning 2.0.0 (SemVer) format; $params returns ['api' => ...]

Patterns are very flexible, allowing them to be modified using a custom regular expression. Replace SemVer format with <major>.<minor>.<revision>.<build> format:

$app->action('GET', '/download/<foobar:version>/<user>', function ($app, $params) { $version = $params['foobar']; ... }); $app->setPattern('version', '\d+\.\d+\.\d+\.\d+');

Replace SemVer format with <major>.<minor> format (useful for web APIs):

$app->action('GET', '/api/<foobar:version>/<user>', function ($app, $params) { $version = $params['foobar']; ... }); $app->setPattern('version', '\d+\.\d+');

Sharing data

The flexibility of the Inphinit\App class allows you to define properties dynamically, providing convenient access to information inside controllers or route callbacks. Example:

$app->scope('https://api.example.com/', function ($app, $params) { $app->userInfo = authUserInfoContext(); $app->customers = customersContext(); Response::type('application/json'); $app->action('GET', '/me', function ($app, $params) { return json_encode($app->userInfo->get()); }); $app->action('GET', '/customers', 'Api\\Clients::list'); $app->action('GET', '/customers/<id:uuid>/orders', 'Api\\Clients::orders'); });

Example of using shared data in the Controller:

<?php namespace Controllers; class FooBar { public function list($app, $params) { return json_encode($app->customers->all()); } public function orders($app, $params) { $customerId = $params['id']; $customer = $app->customers->find($customerId); return json_encode($customer->orders()); } }

Using filters

The route filters are similar to the middleware systems, allowing control the requests in main scope or in others scopes, releasing ou blocking access to the routes. This feature allow create authentication and permission systems for specific routes.

This fictional code demonstrate usage examples of filters in different contexts:

use Inphinit\Http\Request; // Executes in all contexts $app->useFilter(function ($app, $method, $path, $params) { if (country_allowed() === false) { // Sent HTTP 401 to informate to browser/client Request::status(401); // Block access to the routes in all scopes return false; } return true; }); // Executes in all contexts $app->useFilter(function ($app, $method, $path, $params) { // In fictional code checks if HTTP is allowed return allowed_http_method($method); }); $app->scope('https://api.example.com/', function ($app, $params) { Response::type('application/json'); // Executes only in this scope $app->useFilter(function () { // Check if a request is from web browser if (is_web_browser()) { Request::status(403); return false; } return true; }); $app->action('GET', '/delivery', 'Api\\Delivery::list'); $app->action('GET', '/delivery/<id:uuid>/orders', 'Api\\Delivery::orders'); }); // Only main scope filters are executed when access this route: $app->action('GET', '/about', 'Homepage::about');

More features