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 $method, 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());
}
}