Параметры маршрутов
У каждой статьи блога свой адрес: /posts/1, /posts/2 и так далее. Писать маршрут для каждой нельзя, поэтому изменяемую часть адреса объявляют параметром — она начинается с двоеточия.
Параметр в адресе
// start/routes.ts
import router from '@adonisjs/core/services/router'
router.get('/posts/:id', async ({ params }) => {
return `Статья номер ${params.id}`
})Обработчик получает объект контекста запроса, из которого здесь деструктуризацией взято поле params. По адресу /posts/5 страница покажет «Статья номер 5». Значения параметров всегда приходят строками.
Несколько параметров
// start/routes.ts
router.get('/posts/:postId/comments/:commentId', async ({ params }) => {
return `Комментарий ${params.commentId} к статье ${params.postId}`
})Адрес /posts/3/comments/12 вернёт «Комментарий 12 к статье 3».
Необязательный параметр
Знак вопроса после имени делает параметр необязательным:
// start/routes.ts
router.get('/archive/:year?', async ({ params }) => {
const year = params.year ?? 'все годы'
return `Архив: ${year}`
})Подойдут оба адреса: /archive/2025 покажет «Архив: 2025», а /archive — «Архив: все годы».
Проверка формата
Чтобы маршрут срабатывал только для чисел, параметру задают проверку методом where:
// start/routes.ts
router
.get('/posts/:id', async ({ params }) => {
return `Статья номер ${params.id}`
})
.where('id', router.matchers.number())Теперь /posts/15 работает, а /posts/hello вернёт 404. Готовая проверка number() ещё и превращает значение в число, так что params.id будет числом, а не строкой. Есть и другие: router.matchers.uuid() и router.matchers.slug().
Свою проверку можно задать регулярным выражением:
// start/routes.ts
router
.get('/tags/:name', async ({ params }) => `Тег ${params.name}`)
.where('name', /^[a-z]+$/)Ссылка на маршрут с параметром
В шаблоне или в HTML адрес собирают из параметра:
{{-- resources/views/pages/home.edge --}}
<a href="/posts/{{ post.id }}">{{ post.title }}</a>В следующем уроке появится способ лучше — ссылки по имени маршрута.
Частая ошибка
AdonisJS проверяет маршруты в порядке объявления. Маршрут с параметром, стоящий выше, перехватит и конкретный адрес:
// start/routes.ts
// Неправильно: /posts/create попадёт в первый маршрут как id = "create".
router.get('/posts/:id', async ({ params }) => `Статья ${params.id}`)
router.get('/posts/create', async () => 'Новая статья')Ставьте конкретные адреса выше маршрутов с параметрами или ограничьте параметр проверкой number().