Новое в Symfony 4.3: Безусловное включение в URL необязательного параметра маршрута
Перевод статьи 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 вне зависимости от его значения.