Маршрутизація
Маршрутизатор подбає про все, що пов'язано з URL-адресами, так що вам більше не доведеться про них думати. Давайте покажемо:
- як налаштувати маршрутизатор так, щоб URL-адреси були такими, якими ви хочете їх бачити
- як налаштувати SEO та перенаправлення
- як написати свій власний маршрутизатор
Більш людські URL (або круті або красиві URL) зручніші для використання, краще запам'ятовуються і позитивно впливають на SEO. Nette враховує це і повністю задовольняє бажання розробників. Ви можете розробити структуру URL для вашого застосунку саме так, як ви хочете. Ви можете навіть розробити її після того, як застосунок буде готовий, оскільки це можна зробити без будь-яких змін коду або шаблону. Вона визначається елегантним чином в одному єдиному місці, у маршрутизаторі, і не розкидана у вигляді анотацій по всіх презентаторах.
Маршрутизатор у Nette особливий, бо він двонаправлений, він може як декодувати URL HTTP-запитів, так і створювати посилання. Тому він відіграє важливу роль у Nette Application, оскільки він вирішує, який ведучий і дія виконуватимуть поточний запит, а також використовується для генерації URL у шаблоні тощо.
Однак маршрутизатор не обмежується цим застосуванням, ви можете використовувати його в додатках, де ведучі взагалі не використовуються, для REST API тощо. Докладніше в розділі роздільне використання.
Колекція маршрутів
Найбільш приємним способом визначення URL-адрес у додатку є клас Nette\Application\Routers\RouteList. Визначення складається зі списку так званих маршрутів, тобто масок URL-адрес і пов'язаних із ними презентерів і дій за допомогою простого API. Нам не потрібно називати маршрути.
$router = new Nette\Application\Routers\RouteList;
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('article/<id>', 'Article:view');
// ...
У прикладі йдеться про те, що якщо ми відкриємо
https://any-domain.com/rss.xml
з дією rss
і т. д. Якщо відповідний маршрут
не знайдено, застосунок Nette відповідає винятком BadRequestException, який
відображається для користувача як сторінка помилки 404 Not Found.
Порядок маршрутів
Порядок, у якому перелічено маршрути, дуже важливий, тому що вони оцінюються послідовно зверху вниз. Правило полягає в тому, що ми оголошуємо маршрути від конкретних до загальних:
// ПОМИЛКА: 'rss.xml' відповідає першому маршруту і неправильно сприймає його як <slug>.
$router->addRoute('<slug>', 'Article:view');
$router->addRoute('rss.xml', 'Feed:rss');
// ДЕТАЛЬНІШЕ
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('<slug>', 'Article:view');
Маршрути також оцінюються зверху вниз під час генерації посилань:
// ПОМИЛКА: генерує посилання на 'Feed:rss' як 'admin/feed/rss'
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
$router->addRoute('rss.xml', 'Feed:rss');
// ДЕТАЛЬНІШЕ
$router->addRoute('rss.xml', 'Feed:rss');
$router->addRoute('admin/<presenter>/<action>', 'Admin:default');
Ми не будемо приховувати від вас, що для правильної побудови списку потрібна певна навичка. Поки ви не навчитеся, панель routing panel буде корисним інструментом.
Маска і параметри
Маска описує відносний шлях, заснований на корені сайту. Найпростіша маска – це статичний URL:
$router->addRoute('products', 'Products:default');
Часто маски містять так звані параметри. Вони укладені в кутові
дужки (наприклад, <year>
) і передаються в цільовий презентер,
наприклад, у метод renderShow(int $year)
або в постійний параметр
$year
:
$router->addRoute('chronicle/<year>', 'History:show');
У прикладі йдеться про те, що якщо ми відкриємо
https://any-domain.com/chronicle/2020
і дія show
з параметром year: 2020
відображатиметься.
Ми можемо вказати значення за замовчуванням для параметрів безпосередньо в масці, і таким чином вона стає необов'язковою:
$router->addRoute('chronicle/<year=2020>', 'History:show');
Тепер маршрут прийматиме URL https://any-domain.com/chronicle/
з параметром
year
: 2020`.
Звісно, ім'я презентера та дія також можуть бути параметрами. Наприклад:
$router->addRoute('<presenter>/<action>', 'Home:default');
Цей маршрут приймає, наприклад, URL у формі /article/edit
і
/catalog/list
відповідно, і переводить їх у презентери та дії
Article:edit
і Catalog:list
відповідно.
Він також надає параметрам presenter
і action
значення за
замовчуванням Home
і default
і тому вони є необов'язковими.
Тому маршрут також приймає URL /article
і переводить його як
Article:default
. Або навпаки, посилання на Product:default
генерує шлях
/product
, посилання на стандартну Home:default
генерує шлях
/
.
Маска може описувати не тільки відносний шлях, що базується на корені сайту, а й абсолютний шлях, якщо він починається зі слеша, або навіть увесь абсолютний URL, якщо він починається з двох слешів:
// відносний шлях до кореня програми
$router->addRoute('<presenter>/<action>', /* ... */);
// абсолютний шлях, відносно імені хоста сервера
$router->addRoute('/<presenter>/<action>', /* ... */);
// абсолютний URL, включно з ім'ям хоста (щодо схеми)
$router->addRoute('//<lang>.example.com/<presenter>/<action>', /* ... */);
// абсолютний URL, включно зі схемою
$router->addRoute('https://<lang>.example.com/<presenter>/<action>', /* ... */);
Валідаційні вирази
Для кожного параметра можна задати умову перевірки за допомогою регулярного виразу.
Наприклад, давайте задамо id
тільки числовим, використовуючи
\d+
regexp:
$router->addRoute('<presenter>/<action>[/<id \d+>]', /* ... */);
За замовчуванням регулярним виразом для всіх параметрів є [^/]+
,
тобто все, крім слеша. Якщо параметр має відповідати також косій рисі,
ми задаємо регулярний вираз .+
.
// приймає https://example.com/a/b/c, path - 'a/b/c'
$router->addRoute('<path .+>', /* ... */);
Необов'язкові послідовності
Квадратні дужки позначають необов'язкові частини маски. Будь-яка частина маски може бути задана як необов'язкова, включно з тими, які містять параметри:
$router->addRoute('[<lang [a-z]{2}>/]<name>', /* ... */);
// URL-адреси, що приймаються: Параметри:
// /en/download lang => en, name => download
// /download lang => null, name => download
Звичайно, коли параметр є частиною необов'язкової послідовності, він також стає необов'язковим. Якщо у нього немає значення за замовчуванням, він дорівнюватиме null.
Необов'язкові частини також можуть бути в домені:
$router->addRoute('//[<lang=en>.]example.com/<presenter>/<action>', /* ... */);
Послідовності можуть бути вільно вкладені та об'єднані:
$router->addRoute(
'[<lang [a-z]{2}>[-<sublang>]/]<name>[page-<page=0>]',
'Home:default',
);
// URL-адреси, що приймаються:
// /ru/hello
// /en-us/hello
// /hello
// /hello/page-12
Генератор URL намагається зробити URL якомога коротшим, тому те, що
можна опустити, опускається. Тому, наприклад, маршрут index[.html]
генерує шлях /index
. Ви можете змінити цю поведінку, написавши знак
оклику після лівої квадратної дужки:
// приймає /hello і /hello.html, генерує /hello
$router->addRoute('<name>[.html]', /* ... */);
// приймає /hello і /hello.html, генерує /hello.html
$router->addRoute('<name>[!.html]', /* ... */);
Необов'язкові параметри (тобто параметри, що мають значення за замовчуванням) без квадратних дужок поводяться так, як якщо б вони були обгорнуті таким чином:
$router->addRoute('<presenter=Home>/<action=default>/<id=>', /* ... */);
// дорівнює:
$router->addRoute('[<presenter=Home>/[<action=default>/[<id>]]]', /* ... */);
Щоб змінити спосіб генерації самої правої косої риски, тобто замість
/home/
отримати /home
, налаштуйте маршрут таким чином:
$router->addRoute('[<presenter=Home>[/<action=default>[/<id>]]]', /* ... */);
Символи підстановки
У масці абсолютного шляху ми можемо використовувати такі підстановні знаки, щоб уникнути, наприклад, необхідності записувати в маску домен, який може відрізнятися в середовищі розроблення та виробничому середовищі:
%tld%
= домен верхнього рівня, наприклад,com
абоorg
%sld%
= домен другого рівня, наприклад,example
%domain%
= домен без піддоменів, наприклад,example.com
%host%
= весь хост, наприклад,www.example.com
%basePath%
= шлях до кореневого каталогу
$router->addRoute('//www.%domain%/%basePath%/<presenter>/<action>', /* ... */);
$router->addRoute('//www.%sld%.%tld%/%basePath%/<presenter>/<action', /* ... */);
Розширена нотація
Мета маршруту, зазвичай записана у вигляді Presenter:action
, також
може бути виражена за допомогою масиву, який визначає окремі параметри
та їхні значення за замовчуванням:
$router->addRoute('<presenter>/<action>[/<id \d+>]', [
'presenter' => 'Home',
'action' => 'default',
]);
Для більш детальної специфікації можна використовувати ще більш
розширену форму, де на додаток до значень за замовчуванням можна
задати інші властивості параметрів, наприклад, регулярний вираз
перевірки (див. параметр id
):
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>[/<id>]', [
'presenter' => [
Route::Value => 'Home',
],
'action' => [
Route::Value => 'default',
],
'id' => [
Route::Pattern => '\d+',
],
]);
Важливо відзначити, що якщо параметри, визначені в масиві, не включені в маску шляху, їх значення не можуть бути змінені, навіть за допомогою параметрів запиту, зазначених після знака питання в URL-адресі.
Фільтри та переклади
Доброю практикою є написання вихідного коду англійською мовою, але що якщо вам потрібно, щоб URL вашого сайту було перекладено іншою мовою?
$router->addRoute('<presenter>/<action>', 'Home:default');
буде генерувати англійські URL, такі як /product/123
або /cart
.
Якщо ми хочемо, щоб презентери та дії в URL були перекладені німецькою
мовою (наприклад, /produkt/123
або /einkaufswagen
), ми можемо
використовувати словник перекладів. Щоб додати його, нам уже потрібен
„більш зрозумілий“ варіант другого параметра:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterTable => [
// строка в URL => ведущий
'produkt' => 'Product',
'einkaufswagen' => 'Cart',
'katalog' => 'Catalog',
],
],
'action' => [
Route::Value => 'default',
Route::FilterTable => [
'liste' => 'list',
],
],
]);
Для одного і того ж презентера можна використовувати кілька ключів словника. Вони створюватимуть для нього різні псевдоніми. Останній ключ вважається канонічним варіантом (тобто той, який буде в згенерованому URL).
Таблиця перекладу може бути застосована до будь-якого параметра
таким чином. Однак якщо перекладу не існує, береться вихідне значення.
Ми можемо змінити цю поведінку, додавши Route::FilterStrict => true
, і тоді
маршрут відхилятиме URL, якщо значення відсутнє в словнику.
На додаток до словника перекладу у вигляді масиву можна задати власні функції перекладу:
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>/<id>', [
'presenter' => [
Route::Value => 'Home',
Route::FilterIn => function (string $s): string { /* ... */ },
Route::FilterOut => function (string $s): string { /* ... */ },
],
'action' => 'default',
'id' => null,
]);
Функція Route::FilterIn
здійснює перетворення між параметром в URL і
рядком, який потім передають презентувальнику, функція FilterOut
забезпечує перетворення у зворотному напрямку.
Параметри presenter
, action
і module
вже мають зумовлені
фільтри, які конвертують між PascalCase, camelCase і kebab-case відповідно, що
використовуються в URL. Значення параметрів за замовчуванням уже
записано в перетвореній формі, тому, наприклад, у випадку з презентером
ми пишемо <presenter=ProductEdit>
замість <presenter=product-edit>
.
Загальні фільтри
Крім фільтрів для конкретних параметрів, ви також можете визначити
загальні фільтри, які отримують асоціативний масив усіх параметрів,
які вони можуть змінювати будь-яким способом, а потім повертати.
Загальні фільтри визначаються за ключем null
.
use Nette\Routing\Route;
$router->addRoute('<presenter>/<action>', [
'presenter' => 'Home',
'action' => 'default',
null => [
Route::FilterIn => function (array $params): array { /* ... */ },
Route::FilterOut => function (array $params): array { /* ... */ },
],
]);
Загальні фільтри дають вам можливість налаштувати поведінку
маршруту абсолютно будь-яким способом. Ми можемо використовувати їх,
наприклад, для зміни параметрів на основі інших параметрів. Наприклад,
переведення <presenter>
и <action>
на основі поточного
значення параметра <lang>
.
Якщо для параметра визначено користувацький фільтр і одночасно
існує загальний фільтр, користувацький FilterIn
виконується перед
загальним, і навпаки, загальний FilterOut
виконується перед
користувацьким. Таким чином, усередині загального фільтра знаходяться
значення параметрів presenter
і action
відповідно, написані
мовою PascalCase і camelCase відповідно.
Прапор OneWay
Односторонні маршрути використовуються для збереження
функціональності старих URL, які застосунок більше не генерує, але все
ще приймає. Ми позначаємо їх прапором OneWay
:
// старий URL /product-info?id=123
$router->addRoute('product-info', 'Product:detail', $router::ONE_WAY);
// нова URL-адреса /product/123
$router->addRoute('product/<id>', 'Product:detail');
У разі звернення до старої URL-адреси презентер автоматично перенаправляє на нову URL-адресу, щоб пошукові системи не індексували ці сторінки двічі (див. SEO та канонізація).
Динамічна маршрутизація із зворотними дзвінками
Динамічна маршрутизація з функцією зворотного виклику дозволяє безпосередньо призначати маршрутам функції (зворотні виклики), які будуть виконуватися при відвідуванні вказаного шляху. Ця гнучка функція дозволяє швидко та ефективно створювати різні кінцеві точки для вашого додатку:
$router->addRoute('test', function () {
echo 'You are at the /test address';
});
Ви також можете визначити параметри в масці, які будуть автоматично передані вашому зворотному виклику:
$router->addRoute('<lang cs|en>', function (string $lang) {
echo match ($lang) {
'cs' => 'Welcome to the Czech version of our website!',
'en' => 'Welcome to the English version of our website!',
};
});
Модулі
Якщо у нас є кілька маршрутів, що належать одному модулю, ми можемо
використовувати withModule()
для їхнього групування:
$router = new RouteList;
$router->withModule('Forum') // наступні маршрутизатори входять до складу модуля Forum
->addRoute('rss', 'Feed:rss') // презентер Forum:Feed
->addRoute('<presenter>/<action>')
->withModule('Admin') // наступні маршрутизатори є частиною модуля Forum:Admin
->addRoute('sign:in', 'Sign:in');
Альтернативою є використання параметра module
:
// URL manage/dashboard/default відображається на ведучого Admin:Dashboard
$router->addRoute('manage/<presenter>/<action>', [
'module' => 'Admin',
]);
Субдомени
Колекції маршрутів можуть бути згруповані за піддоменами:
$router = new RouteList;
$router->withDomain('example.com')
->addRoute('rss', 'Feed:rss')
->addRoute('<presenter>/<action>');
Ви також можете використовувати Символи підстановки у своєму доменному імені:
$router = new RouteList;
$router->withDomain('example.%tld%')
// ...
Префікс шляху
Колекції маршрутів можуть бути згруповані за шляхом в URL:
$router = new RouteList;
$router->withPath('eshop')
->addRoute('rss', 'Feed:rss') // відповідає URL /eshop/rss
->addRoute('<presenter>/<action>'); // відповідає URL /eshop/<presenter>/<action>
Комбінації
Вищевказані варіанти використання можна комбінувати:
$router = (new RouteList)
->withDomain('admin.example.com')
->withModule('Admin')
->addRoute(/* ... */)
->addRoute(/* ... */)
->end()
->withModule('Images')
->addRoute(/* ... */)
->end()
->end()
->withDomain('example.com')
->withPath('export')
->addRoute(/* ... */)
// ...
Параметри запиту
Маски також можуть містити параметри запиту (параметри після знака питання в URL). Вони не можуть визначити вираз перевірки, але вони можуть змінити ім'я, під яким вони передаються презентувальнику:
// використовуємо параметр запиту 'cat' як 'categoryId' у застосунку
$router->addRoute('product ? id=<productId> & cat=<categoryId>', /* ... */);
Параметри Foo
Тепер ми йдемо глибше. Параметри Foo – це, по суті, неіменовані
параметри, які дозволяють зіставити регулярний вираз. Наступний
маршрут відповідає /index
, /index.html
, /index.htm
і
/index.php
:
$router->addRoute('index<? \.html?|\.php|>', /* ... */);
Також можна явно задати рядок, який буде використовуватися для
генерації URL. Рядок має розташовуватися безпосередньо після знака
запитання. Наступний маршрут схожий на попередній, але генерує
/index.html
замість /index
, тому що рядок .html
встановлено
як „значення, що генерується“.
$router->addRoute('index<?.html \.html?|\.php|>', /* ... */);
Інтеграція
Щоб підключити наш маршрутизатор до застосунку, ми повинні
повідомити про нього контейнер DI. Найпростіший спосіб – це
підготувати фабрику, яка буде створювати об'єкт маршрутизатора, і
повідомити конфігурацію контейнера, щоб вона його використовувала.
Припустимо, ми напишемо для цього метод App\Core\RouterFactory::createRouter()
:
namespace App\Core;
use Nette\Application\Routers\RouteList;
class RouterFactory
{
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute(/* ... */);
return $router;
}
}
Потім ми пишемо в configuration:
services:
- App\Core\RouterFactory::createRouter
Будь-які залежності, такі як підключення до бази даних тощо, передаються методу фабрики як параметри за допомогою autowiring:
public static function createRouter(Nette\Database\Connection $db): RouteList
{
// ...
}
SimpleRouter
Набагато простішим маршрутизатором, ніж колекція маршрутів, є SimpleRouter. Його можна
використовувати, коли немає потреби в певному форматі URL, коли
mod_rewrite
(або альтернативи) недоступний або коли ми просто не
хочемо поки що возитися зі зручними для користувача URL.
Генерує адреси приблизно такої форми:
http://example.com/?presenter=Product&action=detail&id=123
Параметром конструктора SimpleRouter
є презентер і дія за
замовчуванням, тобто дія, яку буде виконано, якщо ми відкриємо,
наприклад, http://example.com/
без додаткових параметрів.
// використовуємо презентер 'Home' і дію 'default'
$router = new Nette\Application\Routers\SimpleRouter('Home:default');
Ми рекомендуємо визначати SimpleRouter безпосередньо в конфігурації:
services:
- Nette\Application\Routers\SimpleRouter('Home:default')
SEO та канонізація
Фреймворк покращує SEO, запобігаючи дублюванню контенту на різних URL.
Якщо кілька адрес посилаються на одне й те саме місце призначення,
наприклад /index
і /index.html
, фреймворк визначає першу з них як
основну (канонічну) і перенаправляє на неї решту за допомогою HTTP-коду
301. Завдяки цьому пошукові системи не будуть індексувати сторінки
двічі і не порушать їхній сторінковий рейтинг.
Цей процес називається канонізацією. Канонічний URL – це URL, згенерований маршрутизатором, тобто першим відповідним маршрутом у колекції без прапора OneWay. Тому в колекції ми перераховуємо первинні маршрути першими.
Канонізація здійснюється презентером, докладніше в розділі Канонізація.
HTTPS
Для того щоб використовувати протокол HTTPS, необхідно активувати його на хостингу та налаштувати сервер.
Перенаправлення всього сайту на HTTPS має бути виконано на рівні сервера, наприклад, за допомогою файлу .htaccess у кореневому каталозі нашого застосунку, з HTTP-кодом 301. Налаштування можуть відрізнятися залежно від хостингу і виглядають приблизно так:
<IfModule mod_rewrite.c>
RewriteEngine On
...
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
...
</IfModule>
Маршрутизатор генерує URL з тим самим протоколом, за яким було завантажено сторінку, тому немає необхідності задавати що-небудь ще.
Однак, якщо нам виключно потрібно, щоб різні маршрути працювали під різними протоколами, ми помістимо це в маску маршруту:
// Згенерує HTTP-адресу
$router->addRoute('http://%host%/<presenter>/<action>', /* ... */);
// Згенерує HTTPS адресу
$router->addRoute('https://%host%/<presenter>/<action>', /* ... */);
Налагоджувач маршрутизації
Смуга маршрутизації, показана в Tracy Bar, є корисним інструментом, який відображає список маршрутів, а також параметри, які маршрутизатор отримав з URL.
Зелена смуга з символом ✓ представляє маршрут, який відповідає поточному URL, сині смуги з символами ≈ вказують на маршрути, які також відповідали б URL, якби зелений колір не обігнав їх. Далі ми бачимо поточного ведучого та дії.
Водночас, якщо відбувається несподіване перенаправлення через канонікалізацію, корисно зазирнути в панель redirect, щоб дізнатися, як маршрутизатор спочатку зрозумів URL і чому він перенаправив.
Під час налагодження маршрутизатора рекомендується відкрити Developer Tools у браузері (Ctrl+Shift+I або Cmd+Option+I) і вимкнути кеш у панелі Network, щоб перенаправлення не зберігалися в ньому.
Продуктивність
Кількість маршрутів впливає на швидкість маршрутизатора. Їхня кількість, звісно, не повинна перевищувати кількох десятків. Якщо ваш сайт має занадто складну структуру URL, ви можете написати Користувацький маршрутизатор.
Якщо маршрутизатор не має залежностей, наприклад, від бази даних, і його фабрика не має аргументів, ми можемо серіалізувати його скомпільовану форму безпосередньо в DI-контейнер і таким чином зробити додаток трохи швидшим.
routing:
cache: true
Користувацький маршрутизатор
Наступні рядки призначені для дуже досвідчених користувачів. Ви можете створити свій власний маршрутизатор і, природно, додати його до колекції маршрутів. Маршрутизатор являє собою реалізацію інтерфейсу Router з двома методами:
use Nette\Http\IRequest as HttpRequest;
use Nette\Http\UrlScript;
class MyRouter implements Nette\Routing\Router
{
public function match(HttpRequest $httpRequest): ?array
{
// ...
}
public function constructUrl(array $params, UrlScript $refUrl): ?string
{
// ...
}
}
Метод match
обробляє поточний $httpRequest, з якого може
бути витягнуто не тільки URL, а й заголовки тощо, у масив, що містить ім'я
ведучого і його параметри. Якщо він не може обробити запит, то повертає
null. Під час обробки запиту ми повинні повернути щонайменше ведучого і
дію. Ім'я ведучого є повним і включає будь-які модулі:
[
'presenter' => 'Front:Home',
'action' => 'default',
]
Метод constructUrl
, з іншого боку, генерує абсолютний URL з масиву
параметрів. Він може використовувати інформацію з параметра
$refUrl
, який є поточним URL.
Щоб додати користувацький маршрутизатор до колекції маршрутів,
використовуйте add()
:
$router = new Nette\Application\Routers\RouteList;
$router->add(new MyRouter);
$router->addRoute(/* ... */);
// ...
Роздільне використання
Під роздільним використанням мається на увазі використання можливостей маршрутизатора в додатку, який не використовує додаток Nette і презентери. До нього можна застосувати майже все, що ми показали в цій главі, з такими відмінностями:
- для колекцій маршрутів ми використовуємо клас Nette\Routing\RouteList.
- як клас простого маршрутизатора Nette\Routing\SimpleRouter.
- оскільки немає пари
Presenter:action
, ми використовуємо Розширену нотацію.
Отже, ми знову додамо метод, який буде створювати, наприклад, маршрутизатор:
namespace App\Core;
use Nette\Routing\RouteList;
class RouterFactory
{
public static function createRouter(): RouteList
{
$router = new RouteList;
$router->addRoute('rss.xml', [
'controller' => 'RssFeedController',
]);
$router->addRoute('article/<id \d+>', [
'controller' => 'ArticleController',
]);
// ...
return $router;
}
}
Якщо ви використовуєте DI-контейнер, як ми рекомендуємо, додайте метод у конфігурацію ще раз, а потім отримайте маршрутизатор разом із HTTP-запитом із контейнера:
$router = $container->getByType(Nette\Routing\Router::class);
$httpRequest = $container->getByType(Nette\Http\IRequest::class);
Або ми будемо створювати об'єкти безпосередньо:
$router = App\Core\RouterFactory::createRouter();
$httpRequest = (new Nette\Http\RequestFactory)->fromGlobals();
Тепер потрібно дати маршрутизатору попрацювати:
$params = $router->match($httpRequest);
if ($params === null) {
// не знайдено співпадаючого маршруту, надішлемо помилку 404
exit;
}
// обробляємо отримані параметри
$controller = $params['controller'];
// ...
І навпаки, ми будемо використовувати маршрутизатор для створення посилання:
$params = ['controller' => 'ArticleController', 'id' => 123];
$url = $router->constructUrl($params, $httpRequest->getUrl());