Новое в Symfony 4.3: Безусловное включение в URL необязательного параметра маршрута

Удальцов Валентин
Пых / PHPYH
Published in
2 min readJan 2, 2019

Перевод статьи New in Symfony 4.3: Always Include Route Default Values.

Маршрутизация в Symfony позволяет указать значение по умолчанию для параметра маршрута. При генерации URL последний параметр маршрута будет опущен, если его значение не передано или совпадает со значением по умолчанию. Рассмотрим пример:

namespace App\Controller;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class BlogController extends AbstractController
{
/**
* @Route("/blog/{page}", name="blog_list")
*/
public function list($page = 1)
{
// ...
}
}

Если вы не укажете значение параметра page при генерации URL на базе маршрута blog_list, результирующим URL будет /blog, а аргумент page будет равен 1:

$router = ... // экземпляр UrlGeneratorInterface$url = $router->generate('blog_list');                // /blog
$url = $router->generate('blog_list', ['page' => 1]); // /blog/1
$url = $router->generate('blog_list', ['page' => 7]); // /blog/7

Как правило, это желаемое поведение в большинстве ситуаций. Но иногда последний параметр должен присутствовать в сгенерированном URL вне зависимости от того, передано значение или нет. В Symfony 4.3 это станет возможным благодаря обновленному синтаксису маршрута:

/**
* @Route("/blog/{!page}", name="blog_list")
*/
public function list($page = 1)
{
// ...
}

Восклицательный знак ! перед именем параметра сообщает роутеру о том, что параметр должен быть включен в URL безусловно:

$url = $router->generate('blog_list');                // /blog/1
$url = $router->generate('blog_list', ['page' => 1]); // /blog/1
$url = $router->generate('blog_list', ['page' => 7]); // /blog/

Добавлено Владимиром Лучаниновым в #29599.

От переводчика

Предлагаю рассмотреть еще один пример из пояснения к PR.

Задача

Организовать маршрутизацию для экспорта новостей в форматах CSV и XML с использованием системного параметра _format. Формат по умолчанию CSV. Расширение должно всегда присутствовать в URL с целью повышения его информативности.

Вариант 1

Зашить расширение в путь и присвоить атрибут вручную:

@Route("/news/export.csv", name="news_export", defaults={"_format": "csv"})
@Route("/news/export.xml", name="news_export_xml", defaults={"_format": "xml"})

Выглядит избыточно; очень неудобно в использовании из-за двух маршрутов.

Вариант 2

Оставить расширение обязательным параметром:

@Route("/news/export.{_format<csv|xml>}", name="news_export")

Придется всегда указывать формат {{ path('export_news', {_format: 'csv'}) }}.

Symfony 4.3

@Route("/news/export.{!_format<csv|xml>?csv}", name="news_export")

Итак, в Symfony 4.3 при помощи записи {!slug} мы сможем гарантировать наличие параметра slug в сгенерированном URL вне зависимости от его значения.

--

--