<form action="/users/<?= $user['id'] ?>" method="post">
  <input type="hidden" name="_METHOD" value="DELETE">
  <input type="submit" value="Remove">
</form>

В примере выше ссылка «зашита» прямо в шаблон. В принципе, ничего криминального, но дальше возможны осложнения. Что если маршрут изменится с /users/{id} на /u/{id}? Придётся пройтись по всем шаблонам и изменить все ссылки. А если этот маршрут удалить? Сайт продолжит работать (и приёмочные тесты тоже), хотя будет лучше если страницы с такими ссылками начнут выдавать ошибки. Тогда выявить подобные ссылки станет крайне просто особенно если есть тесты.

Для решения этой задачи придумали именовать маршруты. Далеко не все микрофреймворки поддерживают именованные маршруты, но Slim здесь отличился в правильную сторону.

<?php

$app->get('/users', function ($request, $response) {
    // ...
})->setName('users');

$app->get('/users/{id}', function ($request, $response) {
    // ...
})->setName('user');

Метод setName задаёт имя маршрута. Затем это имя используется для формирования нужного адреса. Ниже пример того как это сделать:

<?php

$app = AppFactory::create();
// Получаем роутер – объект отвечающий за хранение и обработку маршрутов
$router = $app->getRouteCollector()->getRouteParser();

// Не забываем прокинуть его в обработчик
$app->get('/', function ($request, $response) use ($router) {
    // в функцию передаётся имя маршрута, а она возвращает url
    $router->urlFor('users'); // /users
    $router->urlFor('user', ['id' => 4]); // /users/4
});

В реальных приложениях ссылки формируются во многих частях приложениях:

  • В шаблонах
  • В обработчиках (при редиректах)
  • В письмах

Поэтому большинство фреймворков предоставляют готовую функцию, которую можно использовать везде где формируются ссылки. К сожалению, PHP-View, который мы используем, не добавляет этот метод в шаблоны (по крайней мере пока), в отличие от Twig-View. В последнем ссылки в шаблонах строятся так:

{% extends "layout.html" %}

{% block body %}
<h1>User List</h1>
<ul>
    <li><a href="{{ path_for('profile', { 'name': 'andrew' }) }}">Andrew</a></li>
</ul>
{% endblock %}

Самостоятельная работа

  1. Сделайте все маршруты именованными.
  2. Сделайте так чтобы в обработчиках обращение ко всем маршрутам было через их имена.
Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →