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 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 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>);
The <handler>
placeholder you saw is where you can put the route logic and it can be contained on the following:
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:
index.phpRoute\get('/hello/{name}', 'pages/home.php');
pages/home.phpecho '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:
HTTP Verb | URI | File |
GET |
|
|
GET |
|
|
POST |
|
|
GET |
|
|
GET |
|
|
PUT |
|
|
DELETE |
|
|
The file structure should look like:
index.php/api└── /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.
Route\files('controllers');
Siler will interpret periods (.) as slashes and also maintain folder structure at HTTP path:
Filename | Method | Path |
| GET |
|
| POST |
|
| GET |
|
| GET |
|
| GET |
|
| GET |
|
| GET |
|
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 @
:
Filename | Method | Path |
| GET |
|
| GET |
|
| GET |
|
Any method is valid, it is guessed based on the penultimate "token":
Filename | Method | Path |
| OPTIONS |
|
| X-CUSTOM |
|
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();
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');