use Siler\Route;

Route\get('/path', <handler>);
Route\post('/path', <handler>);
Route\put('/path', <handler>);
Route\delete('/path', <handler>);
Route\options('/path', <handler>);

Also a facade to catch any HTTP method:

Route\any('/path', <handler>);

Additional and custom HTTP methods can be set using the route function:

Route\route('custom', '/path', <handler>);

With an array, you can listen for multiple HTTP methods on the same handler:

Route\route(['post', 'put'], '/path', <handler>);

Route parameters

Route parameters can be defined using Regular Expressions:

Route\get('/number/([0-9]+)', <handler>);

Or using a little syntax for creating named groups, that is just wrapping the parameter name around curly-brackets:

Route\get('/number/{n}', <handler>);

The above will match anything, not only numbers. For a fine-grained control, please use Regular Expressions.

Optional parameters

Optional named parameters can be defined using the question mark ? as sufix:

Route\get('/hello/{name}?', <handler>);

To avoid the need of a trailing slash, add a question mark after it, like regex (because it is regex):

Route\get('/hello/?{name}?', <handler>);

Route handlers

The <handler> placeholder you saw is where you can put the route logic and it can be contained on the following:


As Anonymous functions:

Route\get('/hello/{name}', function (array $routeParams) {
    echo 'Hello '.($routeParams['name'] ?? 'World');

As a Closures:

$handler = function (array $routeParams) {
    echo 'Hello World';  

function create_handler() {
    return function (array $routeParams) {
        echo 'Hello World';

Route\get('/', $handler);
Route\get('/', create_handler());

As a method call on array-syntax:

class Hello {
    public function world(array $routeParams) {
        echo 'Hello World';

$hello = new Hello();
Route\get('/', [$hello, 'world']);

As a static method call string-syntax:

class Hello {
    static public function world(array $routeParams) {
        echo 'Hello World';

Route\get('/', 'Hello::world');

As any kind of callable:

class Hello {
    public function __invoke(array $routeParams) {
        echo 'Hello World';

Route\get('/', new Hello());


Handlers can be a String representing the filename of another PHP file, route parameters will be available at the global $params variable:

Route\get('/hello/{name}', 'pages/home.php');
echo 'Hello '.$params['name'];


CRUD routes can be auto-magically be defined for convenience using the Rails and Laravel pattern.

Given this resource declaration:

Route\resource('/users', 'api/users');

Siler will look for files at path/to/files matching the HTTP URI according to the table below:

The file structure should look like:

└── /users
    ├─ index.php
    ├─ create.php
    ├─ store.php
    ├─ show.php
    ├─ edit.php
    ├─ update.php
    └─ destroy.php


You can also let Siler create the routes recursively looking for files at a base path. Then the files names will be used to define the method and the path.


Siler will interpret periods (.) as slashes and also maintain folder structure at HTTP path:

Since { and } are valid chars in a filename, route parameters should work as well, but you can define required parameters prefixing with $ and optional parameters using @:

Any method is valid, it is guessed based on the penultimate "token":

Note on handlers

When creating routes, be careful about early and lazy evaluations.

Route\get('/foo', [new FooController(), 'index']);

The example above is early, which means it will call FooController constructor for each request even if it's not a request to /foo.

To make it lazy you can wrap inside a Closure:

Route\get('/foo', function () {
  $controller = new FooController();
  return $controller->index();

Now FooController is called only when there is a match for route /foo. One downside is that now you have to explicitly manage path parameters, on the other hand is a best practice to do so. It is a good time to validate parameters, convert plain string parameters to meaningful types on your domain or resolve dependencies.

Route\get('/users/{id}', function (array $params) use ($ioc) {  
  if (!preg_match('/[0-9]+/', $params['id']) {
    $controller = $ioc->resolve(ErrorController::class);
    return $controller->invalid('IDs must be numbers');
  $controller = $ioc->resolve(UsersController::class);
  return $controller->show($params['id']);



You can grab the raw request body using:

use Siler\Http\Request;

$body = Request\raw();

Parse as URL-encoded data using:

$params = Request\params();

Parse as JSON using:

$resource = Request\json();

$_GET and $_POST superglobals

Or get data from a Form and from the Query String using:

$input = Request\post('input');
$searchTerm = Request\get('q');

Calling them without arguments will tell Siler to return all the values as an array:

$data = Request\post();
$queryString = Request\get();

You can also pass a default value if the key isn't present in the GET or POST super-globals:

$input = Request\post('input', 'default-value');


Also conveniently get a header as easy as for the body:

$contentType = Request\header('Content-Type');

e.g. Serving both JSON and Form requests:

$data = Request\header('Content-Type') == 'json' ? Request\json() : Request\post();


Siler also have convenient functions to simplify HTTP responses.

You can output JSON encoded body with proper headers in just one line:

use Siler\Http\Response;

Response\json(['error' => false, 'message' => 'It works']);

It will already output the given data, you don't need to call echo or print so use carefully, it's not a encoder, it's an output-er.


Same easy as for Request, you can set HTTP response headers with the header function at Response namespace:

Response\header('Access-Control-Allow-Origin', 'https://know-domain.tld');
Response\header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');

Last updated