# Class HttpSoft\Router\Route

Class representing a single route.

Source code on GitHub.

use HttpSoft\Router\Route;

/**
 * @var mixed $handler
 */

$route = new Route('page', '/page/{token}', $handler, ['GET', 'POST']);

$route->getName(); // 'page'
$route->getPattern(); // '/page/{token}'
$route->getHandler(); // $handler
$route->getMethods(); // ['GET', 'POST']
$route->getTokens(); // []
$route->getDefaults(); // []
$route->getHost(); // null
$route->getMatchedParameters(); // []
$route->isAllowedMethod('GET'); // true
$route->isAllowedMethod('PUT'); // false

When adding the {token} placeholder parameter to the path, the regular expression [^/]+ will be used by default, which matches everything except the slash that points to the next segment of the path.

To specify custom regular expressions for placeholder parameter tokens, use the tokens() method.

$route = (new Route('post.view', '/post/{slug}{format}', $handler))
    ->tokens(['slug' => '[\w\-]+', 'format' => '\.[a-zA-z]{3,}'])
;

$route->path(['slug' => 'post-slug', 'format' => '.html']); // '/post/post-slug.html'

You can set the token to the default value using the defaults() method.

$route = (new Route('post.view', '/post/{slug}{format}', $handler))
    ->tokens(['slug' => '[\w\-]+', 'format' => '\.[a-zA-z]{3,}'])
    ->defaults(['format' => '.html'])
;

$route->path(['slug' => 'post-slug']); // '/post/post-slug.html'

Using the host() method, you can specify a specific host for route.

$route = (new Route('page', '/page', $handler))
    ->host('example.com')
;

$route->getHost(); // 'example.com'

Tokens of the route enclosed in [...] are considered optional.

$route = (new Route('post.list', '/posts{[page]}', $handler))
    ->tokens(['page' =>  '\d+'])
;

$route->path(['page' => 33]); // '/posts/33'
$route->path(); // '/posts'

Optional parameters SHOULD only be located at the very end of the route.

Note that the leading slash separator does not need to be placed before the optional parameter token.

You can also set the default value for the optional parameter token.

$route = (new Route('post.list', '/posts{[page]}', $handler))
    ->tokens(['page' =>  '\d+'])
    ->defaults(['page' =>  '1'])
;

$route->path(); // '/posts/1'
$route->path(['page' => null]); // '/posts'

Sometimes it is useful to have a route with several optional parameters in a row.

// `{[year/month/day]}` equivalently to `{[/year/month/day]}`
$route = (new Route('post.archive', '/post/archive{[year/month/day]}', $handler))
    ->tokens(['year' => '\d{4}', 'month' => '\d{2}', 'day' => '\d{2}'])
;

// '/post/archive'
$route->path(['year' => null, 'month' => null, 'day' => null]);
// Or 
$route->path();

// '/post/archive/2020/09/12'
$route->path(['year' => '2020', 'month' => '09', 'day' => '12']);
// '/post/archive/2020/09'
$route->path(['year' => '2020', 'month' => '09']);
// '/post/archive/2020'
$route->path(['year' => '2020']);

This class can generate the path and URL from the route parameters, as well as check for a match with the HTTP request.

use HttpSoft\Message\Uri;
use HttpSoft\Router\Route;

/**
 * @var mixed $handler
 * @var Psr\Http\Message\ServerRequestInterface $request
 */

$route = (new Route('page', '/page/{require}{[optional]}', $handler))
    ->tokens(['require' => '\d+', 'optional' => '[\w-]+'])
    ->defaults(['require' => 1])
    ->host('example.com')
;

$route->match($request->withUri(new Uri('/page/slug'))); // false
$route->getMatchedParameters(); // []

$route->match($request->withUri(new Uri('/page/11'))); // true
$route->getMatchedParameters(); // ['require' => '11']

$route->match($request->withUri(new Uri('/page/25/slug'))); // true
$route->getMatchedParameters(); // ['require' => '11', 'optional' => 'slug']

$route->path(); // '/page/1'
$route->path(['require' => 11]); // '/page/11'
$route->path(['require' => 11, 'optional' => 'slug']); // '/page/11/slug'

$route->url(['require' => 11]); // '//example.com/page/11'
$route->url(['require' => '123'], true); // 'https://example.com/page/123'
$route->url(['require' => '123'], false); // 'http://example.com/page/123'

# Public methods

/**
 * @param string $name unique route name.
 * @param string $pattern path pattern with parameters.
 * @param mixed $handler action, controller, callable, closure, etc.
 * @param array $methods allowed request methods of the route.
 */
public function __construct(string $name, string $pattern, $handler, array $methods = []);

# getName

Gets the unique route name.

public function getName(): string;

# getPattern

Gets the value of the cookie.

public function getPattern(): string;

# getHandler

Gets the route handler.

/**
 * @return mixed
 */
public function getHandler();

# getMethods

Gets the allowed request methods of the route.

/**
 * @return string[]
 */
public function getMethods(): array;

# getTokens

Gets the parameter tokens, as parameter names => regexp tokens.

/**
 * @return array<string, string|null>
 */
public function getTokens(): array;

# getDefaults

Gets the default parameter values, as parameter names => default values.

/**
 * @return array<string, string>
 */
public function getDefaults(): array;

# getHost

Gets the host of the route, or null if no host has been set.

public function getHost(): ?string;

# getMatchedParameters

Gets the matched parameters as parameter names => parameter values.

/**
 * @return array<string, string>
 */
public function getMatchedParameters(): array;

The matched parameters appear may after successful execution of the match() method.

# isAllowedMethod

Checks whether the request method is allowed for the current route.

public function isAllowedMethod(string $method): bool;

The passed method is case-insensitive.

# tokens

Adds the parameter tokens and returns itself.

/**
 * @param array<string, mixed> $tokens `parameter names` => `regexp tokens`
 */
public function tokens(array $tokens): self;

If the parameter token is not scalar or null, the HttpSoft\Router\Exception\InvalidRouteParameterException exception will be thrown.

/**
 * @var mixed $handler
 */

$route = new Route('page', '/page/{id}', $handler);
$route->getTokens(); // []

$route->tokens(['id' => '\d+']);
$route->getTokens(); // ['id' => '\d+']

$route->tokens(['id' => fn() => null]); // throws InvalidRouteParameterException

# defaults

Adds the default parameter values and returns itself.

/**
 * @param array<string, mixed> $defaults `parameter names` => `default values`
 */
public function defaults(array $defaults): self;

If the default parameter value is not scalar, the HttpSoft\Router\Exception\InvalidRouteParameterException exception will be thrown.

/**
 * @var mixed $handler
 */

$route = new Route('page', '/page/{id}', $handler);
$route->getDefaults(); // []

$route->defaults(['id' => 1]);
$route->getDefaults(); // ['id' => 1]
$route->path(); // '/page/1'

$route->defaults(['id' => fn() => null]); // throws InvalidRouteParameterException

# host

Sets the route host and returns itself.

/**
 * @param string $host hostname or host regexp.
 */
public function host(string $host): self;

All leading and trailing slashes will be removed, and all dots in the regular expression will be automatically escaped.

/**
 * @var mixed $handler
 */

$route = new Route('page', '/page/{id}', $handler);
$route->getHost(); // null

// Only for example.com
$route->host('example.com');
$route->getHost(); // 'example.com'

// Only for subdomain.example.com
$route->host('///subdomain.example.com///');
$route->getHost(); // 'subdomain.example.com'

// For any subdomain
$route->host('(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?).example.com');

# match

Checks whether the request URI matches the current route.

public function match(Psr\Http\Message\ServerRequestInterface $request): bool;

If there is a match and the route has matched parameters, they will be saved and available via the getMatchedParameters() method.

use HttpSoft\Message\Uri;

/**
 * @var mixed $handler
 * @var Psr\Http\Message\ServerRequestInterface $request
 */

$route = (new Route('page', '/page/{id}', $handler))
    ->tokens(['id' => '\d+'])
;

$route->match($request->withUri(new Uri('/page/11'))); // true
$route->getMatchedParameters(); // ['id' => '11']

$route->match($request->withUri(new Uri('/page/slug'))); // false
$route->getMatchedParameters(); // []

# path

Generates the URL path from the route parameters.

/**
 * @param array $parameters 'parameter name` => `parameter value`.
 */
public function path(array $parameters = []): string;

If the parameter value does not match its regular expression, or the required parameter is null, the HttpSoft\Router\Exception\InvalidRouteParameterException exception will be thrown.

/**
 * @var mixed $handler
 */

$route = (new Route('post', '/post/{tag}{[id]}', $handler))
    ->tokens(['tag' => '[\w-]+', 'id' => '\d+'])
;

$route->path(['tag' => 'tag-slug', 'id' => '11']); // '/post/tag-slug/11'
$route->path(['tag' => 'tag-slug', 'id' => null]); // '/post/tag-slug'
$route->path(['tag' => 'tag-slug']); // '/post/tag-slug'

$route->path(); // throws InvalidRouteParameterException
$route->path(['tag' => null]); // throws InvalidRouteParameterException
$route->path(['id' => 11]); // throws InvalidRouteParameterException
$route->path(['tag' => 'tag-slug', 'id' => 'slug']); // throws InvalidRouteParameterException

# url

Generates the URL from the route parameters.

/**
 * @param array $parameters 'parameter name` => `parameter value`.
 * @param bool|null $secure If `true`, then `https`. If `false`, then `http`. If `null`, then without the protocol.
 */
public function url(array $parameters = [], bool $secure = null): string;

If the host or the parameter value does not match its regular expression, or the required parameter is null, the HttpSoft\Router\Exception\InvalidRouteParameterException exception will be thrown.

/**
 * @var mixed $handler
 */

$route = new Route('home', '/', $handler);
$route->url([], 'any-host.com'); // '//any-host.com'
$route->url([], 'any-host.com', true); // 'https://any-host.com'
$route->url([], 'any-host.com', false); // 'http://any-host.com'

$route = (new Route('post', '/post/{id}', $handler))
    ->tokens(['id' => '\d+'])
    ->host('(shop|blog).example.com')
;

$route->url(['id' => 11]); // '/post/11'
$route->url(['id' => 11], 'shop.example.com'); // '//shop.example.com/post/11'
$route->url(['id' => '1'], 'blog.example.com', true); // 'https://blog.example.com/post/1'
$route->url(['id' => '1'], 'shop.example.com', false); // 'http://shop.example.com/post/1'

$route->url(); // throws InvalidRouteParameterException
$route->url(['id' => null]);; // throws InvalidRouteParameterException
$route->url(['id' => 'slug']);; // throws InvalidRouteParameterException
$route->url(['id' => 11], 'forum.example.com');; // throws InvalidRouteParameterException

If no host has been passed, then this method will be equivalent to the path() method.