# Класс HttpSoft\Router\RouteCollection

Коллекция маршрутов, реализующая HttpSoft\Router\RouteCollectionInterface.

Исходный код на GitHub.

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

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

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

$routes = new RouteCollection();
$routes->set($route);

$routes->match($request->withUri(new Uri('/post/11'))); // $route
$routes->match($request->withUri(new Uri('/post/slug'))); // null

$routes->path('post', ['id' => 11]); // '/post/11'
$routes->url('post', ['id' => 11]); // '/post/11'

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

$routes->get('post'); // $route
$routes->has('post'); // true

$routes->remove('post'); // $route
$routes->has('post'); // false

$routes->clear();
$routes->getAll(); // []

# Публичные методы

Оригинальное подробное описание методов смотрите в HttpSoft\Router\RouteCollectionInterface.

# set

Устанавливает маршрут.

public function set(HttpSoft\Router\Route $route): void;

Если маршрут уже существует, будет брошено исключение HttpSoft\Router\Exception\RouteAlreadyExistsException.

# get

Возвращает маршрут с указанным именем.

public function get(string $name): Route;

Если маршрут не существует, будет брошено исключение HttpSoft\Router\Exception\RouteNotFoundException.

# getAll

Возвращает все маршруты или пустой массив, если маршрутов не существует.

/**
 * @return HttpSoft\Router\Route[]
 */
public function getAll(): array;

# getIterator

Возвращает внешний итератор с маршрутами.

public function getIterator(): ArrayIterator;

# has

Проверяет, существует ли маршрут с указанным именем.

public function has(string $name): bool;

# remove

Удаляет и возвращает удаленный маршрут.

public function remove(string $name): Route;

Если маршрут не существует, будет брошено исключение HttpSoft\Router\Exception\RouteNotFoundException.

# clear

Удаляет все маршруты.

public function clear(): void;

# count

Возвращает количество маршрутов.

public function count(): int;

# match

Сопоставляет запрос с известными маршрутами.

/**
 * @param Psr\Http\Message\ServerRequestInterface $request экземпляр запроса сервера, реализующий PSR-7.
 * @param bool $checkAllowedMethods следует ли проверять соответствие метода запроса с методами маршрута.
 * @return Psr\Http\Message\ResponseInterface совпавший маршрут или null, если запрос не совпадает с маршрутами.
 */
public function match(
    ServerRequestInterface $request, 
    bool $checkAllowedMethods = true
): ?Route;

Сопоставляется URI запроса с каждым маршрутом, а также метод запроса с разрешенными методами маршрута, если $checkAllowedMethods === true.

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

/**
 * @var mixed $handler
 * @var HttpSoft\Router\RouteCollection $routes
 * @var Psr\Http\Message\ServerRequestInterface $request
 */

$routeAction = (new Route('post.action', '/post/{action}/{id}', $handler, ['GET', 'POST']))
    ->tokens(['action' => '[\w-]+', 'id' => '\d+'])
;
$routeDelete = (new Route('post.delete', '/post/delete/{id}', $handler, ['DELETE']))
    ->tokens(['id' => '\d+'])
;

$routes->set($routeDelete);
$routes->set($routeAction);

$request = $request->withUri(new Uri('/post/create/11'));
$routes->match($request->withMethod('GET')); // $routeAction
$routes->match($request->withMethod('POST')); // $routeAction
$routes->match($request->withMethod('DELETE'), false); // $routeAction
$routes->match($request->withMethod('DELETE')); // null

$request = $request->withUri(new Uri('/post/delete/11'));
$routes->match($request->withMethod('GET')); // null
$routes->match($request->withMethod('POST')); // null
$routes->match($request->withMethod('DELETE')); // $routeDelete
$routes->match($request->withMethod('POST'), false); // $routeDelete

$request = $request->withUri(new Uri('/post/delete'));
$routes->match($request->withMethod('GET')); // null
$routes->match($request->withMethod('POST')); // null
$routes->match($request->withMethod('DELETE')); // null
$routes->match($request->withMethod('DELETE'), false); // null

Сопоставление запроса с маршрутами выполняется в цикле, поэтому приоритетные маршруты должны быть установлены до общих маршрутов.

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

/**
 * @var mixed $handler
 * @var HttpSoft\Router\RouteCollection $routes
 * @var Psr\Http\Message\ServerRequestInterface $request
 */

$routeAction = (new Route('post.action', '/post/{action}/{id}', $handler))
    ->tokens(['action' => '[\w-]+', 'id' => '\d+'])
;
$routeDelete = (new Route('post.delete', '/post/delete/{id}', $handler))
    ->tokens(['id' => '\d+'])
;

// Корректно
$routes->set($routeDelete);
$routes->set($routeAction);
// совпадает с `$routeDelete`
$routes->match($request->withUri(new Uri('/post/delete/11')));

// Некорректно
$routes->set($routeAction);
$routes->set($routeDelete);
// совпадает с `$routeAction`
$routes->match($request->withUri(new Uri('/post/delete/11')));

# path

Генерирует путь URL-адреса по имени и параметрам маршрута.

/**
 * @param string $name имя маршрута.
 * @param array $parameters `имя параметра` => `значение параметра`.
 */
public function path(string $name, array $parameters = []): string;

Если маршрут не существует, будет брошено исключение HttpSoft\Router\Exception\RouteNotFoundException.

Если значение параметра не соответствует его регулярному выражению или обязательный параметр имеет значение null, будет брошено исключение HttpSoft\Router\Exception\InvalidRouteParameterException.

use HttpSoft\Router\Route;

/**
 * @var mixed $handler
 * @var HttpSoft\Router\RouteCollection $routes
 */

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

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

$routes->path('post'); // throws InvalidRouteParameterException
$routes->path('post', ['tag' => null]); // throws InvalidRouteParameterException
$routes->path('post', ['id' => 11]); // throws InvalidRouteParameterException
$routes->path('post', ['tag' => 'tag-slug', 'id' => 'slug']);; // throws InvalidRouteParameterException
$routes->path('not-exist', ['tag' => 'tag-slug', 'id' => 11]); // throws RouteNotFoundException

# url

Генерирует URL-адрес по имени и параметрам маршрута.

/**
 * @param string $name имя маршрута.
 * @param array $parameters `имя параметра` => `значение параметра`.
 * @param string|null $host компонент хоста URI.
 * @param bool|null $secure Если `true`, то `https`. Если `false`, то `http`. Если `null`, то без протокола.
 */
public function url(
    string $name,
    array $parameters = [],
    string $host = null,
    bool $secure = null
): string;

Если маршрут не существует, будет брошено исключение HttpSoft\Router\Exception\RouteNotFoundException.

Если хост или значение параметра не соответствует его регулярному выражению, или обязательный параметр имеет значение null, будет брошено исключение HttpSoft\Router\Exception\InvalidRouteParameterException.

use HttpSoft\Router\Route;

/**
 * @var mixed $handler
 * @var HttpSoft\Router\RouteCollection $routes
 */

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

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

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

$routes->url('post'); // throws InvalidRouteParameterException
$routes->url('post', ['id' => null]);; // throws InvalidRouteParameterException
$routes->url('post', ['id' => 'slug']);; // throws InvalidRouteParameterException
$routes->url('post', ['id' => 11], 'forum.example.com');; // throws InvalidRouteParameterException
$routes->url('not-exist', ['id' => 11]); // throws RouteNotFoundException

Если хост не был передан, этот метод будет эквивалентен методу path().