**Routing**

Tonka is heavily inspired by Laravel and Express JS for its routing. Laravel is the model and ExpressJS is the expression.

The most basic routes accept a URI and an anonymous function, providing a very simple and expressive method for defining routes without complicated routing configuration files:

```php
Route::get('/', fn() => view('home'));
```

## Routes files
It becomes interesting for teams when each member has his own route file. A routes file can be defined anywhere in the project folder, but the best place is the `routes` directory. Tonka by default offers two routes files located in the routes directory. The `routes/web.php` file defines the routes for the web interfaces. To these routes web middleware is assigned with features like session storage and CSRF. The routes in the `routes/api.php` file define the routes for the API interfaces and benefit by default from JWT middelware to distribute JWT tokens. The tokens are not saved anywhere on the server and only the client has a copy. Each token will be identified by its signature. A robust encryption technique is used to generate token signatures. The value of the APP_KEY environment variable is used as the secret key. This key can be regenerated by the `app:key` command under console.

Routes defined in the routes/api.php file belong to a route group called `api` and 'api' prefix will be prepend to those routes automatically. On the other hand, this prefix can be personalized as well as other options in the group by modifying the `App\Providers\RouteServiceProvider` class.

## Verbs
Routes use a number of methods called verbs to respond to http requests. Sometimes you may need to register a route to responds to multiple HTTP verbs.

### GET
```php
Route::get($route, $action);
```

Let's define the login page route.

```php
Route::get('/login', fn() => view('login'));
```

### POST
```php
Route::post($route, $action);
```

Let's define the register page route.

```php
Route::get('/register', fn() => view('register'));
```

### DELETE
```php
Route::delete($route, $action);
```

### PATCH
```php
Route::patch($route, $action);
```

### PUT
```php
Route::put($route, $action);
```
### MATCH
```php
Route::match($verbs, string $route, $action);
```
# Route parameters

## Required parameters
Sometimes you will need to capture segments of the URI within your route. For example, you may need to capture a user's ID from the URL. You may do so by defining route parameters:

```php
Route::get('/users/:id', fn(int $id) => "User $id");
```
!> Parameter passed to the closure function must always have a type.

You may define as many route parameters as required by your route:

```php
Route::get('/users/:id/:hash', fn(int $id, string $hash) => "User $id => Hash $hash");
```
Route parameters are always preceded by two dots (:) and should consist of alphabetic characters. Underscores (_) are also acceptable within route parameter names. Route parameters are injected into route callbacks/controllers based on their order - the names of the route callback/controller arguments must match corresponding parameter name as well as their type.

## Optional parameters
Occasionally you may need to specify a route parameter that may not always be present in the URI. You may do so by placing a `?` mark before the parameter name preceded by double dots (:). Make sure to place them at the end of the route:

```php
Route::get('/users/:id/?:hash', fn(int $id, string $hash) => "User $id => Is hash set ? " . isset($hash) ? true: false);
```
# Route validation
You may constrain the value of your route parameters using the where method on a route instance. The where method accepts the name of the parameter and a validation logic:

```php
Route::get('users/:id', fn(int $id) => "User $id")->where('id', 'required|id|model:user');
```

We are telling the route to match the parameter `id` to an existing user. If user can not being found the route will fail.

!> Beware! When your route contains even a single optional parameter, the `where()` must be replaced by `pattern()` method.

A validator is a sub class of `Clicalmani\Fundation\Validation\InputValidator`. Which means you can create your own validators ([Custom Validators](requests/validation.md)). By default Tonka comes with a preset of validators you can use on any route, any request or any database entity. 

When you specify `required` as the first option of a validator, that will make the validation to fail if the validated value is not set. You can also use `nullable` if you want to tell the validator to accept `NULL` value. But make sure to place it at the end of the validation logic.

Here are some default validators you may use on routes.

## Regular expression validator
```php
Route::get('/users/:phone', fn(string $phone) => "Phone: $phone")->where('phone', 'required|regex|pattern:[0-9]{8}');
```
## Email validator
```php
Route::get('/users/:email', fn(string $email) => "Email: $email")->where('phone', 'required|email');
```
## ID validator
```php
Route::get('/users/:id', fn(string $id) => "User: $id")->where('phone', 'required|id|model:user');
```
!> ID validator defines a `model` option which must be set a model class name in lower case. If your model name is in camel case, use underscore (_).

## Navigation guard validator
A navigation guard is a custom validator you may define directly on the route by calling `guardAgainst()` method. The `guardAgainst()` method accept two parameters: the first parameter is a parameter name and the second argument is closure function that receive the parameter value as only argument and returns a boolean value to indicate that the parameter is valid or not.

```php
Route::get('/users/:phone', fn(string $phone) => "Phone: $phone")->guardAgainst('phone', function(string $phone) {
    return !!preg_match('/^[0-9]{8}$', $phone);
});
```