URL на основе пользовательских (статических) маршрутов
Предупреждение
Чтобы использовать эту функцию, включите PimcoreStaticRoutesBundle в вашем файле bundle.php и установите его соответствующим образом с помощью следующей команды:
bin/console pimcore:bundle:install PimcoreStaticRoutesBundle
Введение
Статические маршруты необходимы для функциональностей, где у вас нет базового документа или где требуется динамические URL. Например, у вас есть список новостей, который генерируется из списка объектов Pimcore, и вы хотите предоставить новостям страницу деталей. Или вы хотите создавать списки продуктов с карточками товаров, страницы корзины, процесс оформления заказа и т. п.
Во всех случаях, когда документы (Documents) непрактичны, на помощь приходят пользовательские маршруты (Custom Routes), позволяющие определять шаблоны URL, которые перенаправляются на конкретные контроллеры с определёнными представлениями.
Пользовательские маршруты занимают четвёртое место в порядке обработки маршрутов.
Пользовательские маршруты являются альтернативой возможностям маршрутизации Symfony и дают немного больше гибкости, но вы всё ещё можете параллельно использовать возможности маршрутизации Symfony (например, атрибут #[Route], routing.yaml и т. п.) вместе с пользовательскими маршрутами Pimcore.
Настройка пользовательских маршрутов
Пользовательские маршруты настраиваются в интерфейсе бэкенда Pimcore следующим образом.

Имеются следующие опции:
- Name - имя пользовательского маршрута для его идентификации
- Pattern - шаблон URL, заданный с помощью регулярного выражения
- Reverse - обратный шаблон, который используется для генерации URL для этого маршрута; см. также раздел Формирование URL.
- Controller - конфигурация модуль/контроллер/действие, на который делегируется запрос. В качестве имени контроллера также можно указать сервис.
- Variables - список имён (через запятую) для заполнительных переменных (placeholder) в регулярном выражении шаблона. Как минимум, все переменные, используемые в обратном шаблоне, должны быть перечислены здесь.
- Defaults - значения по умолчанию для переменных, разделённые символом |, например key=value|key2=value2
- Site - сайт, для которого должен применяться этот маршрут.
- Priority - приоритет при разрешении шаблона URL.
- Methods - определяет, какие HTTP-методы допустимы. Можно указать несколько через запятую. Если пусто, разрешены все методы. (один из
HEAD,GET,POST,PUT,PATCH,DELETE,PURGE,OPTIONS,TRACEилиCONNECT)
Маршруты сохраняются в PHP-конфигурационных файлах в файловой системе(var/config/staticroutes.php), поэтому их также можно редактировать напрямую в вашем любимом IDE и отслеживать изменения в вашей системе контроля версий (например, Git).
Доступ к переменным в контроллере
Вот как вы можете получить (из действия контроллера) значения переменных (заполнителей), которые вы указали в пользовательском маршруте:

<?php
namespace App\Controller;
use Pimcore\Controller\FrontendController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class NewsController extends FrontendController
{
public function detailAction(Request $request): Response
{
$id = $request->query->getInt('news');
$text = $request->query->getString('text');
// ...
return $this->render('news/detail.html.twig');
}
}
К переменным по умолчанию можно обращаться таким же образом.
Использование распознавателя параметров для преобразования ID в объект данных
В Pimcore есть встроенный распознаватель параметров (param resolver) для преобразования ID объектов данных в параметрах запроса в реальные объекты.
Чтобы использовать резолвер параметров, просто укажите тип аргумента (пример для маршрутизации Symfony):
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
....
#[Template('/news/test')]
#[Route('/news/{news}')]
public function detailAction(DataObject\News $news): array
{
return [
'news' => $news
];
}
Распознаватели параметров работают как с пользовательскими маршрутами Pimcore, так и с маршрутами Symfony.
Используя атрибут #[DataObjectParam], можно передавать дополнительные опции для объекта, например работать с неопубликованными объектами.
public function detailAction(
#[DataObjectParam(unpublished: true)] DataObject\News $news
): Response {
...
}
Формирование URL на основе пользовательских маршрутов
URL генерируются с использованием стандартных расширений Twig, предоставляемых Symfony: path() и url(). В дополнение к стандартным расширениям для генерации URL, Pimcore предлагает специальное расширение шаблонизатора (pimcore_url()), чтобы генерировать URL так, как это делалось в Pimcore 4.
Вы можете определить заполнитель в обратном шаблоне с помощью %NAME, а также возможно определить опциональную часть: чтобы сделать часть необязательной, просто заключите её в фигурные скобки (см. пример ниже).
| Name | Pattern | Reverse | Controller | Variables | Defaults | Site IDs | Priority | Methods |
|---|---|---|---|---|---|---|---|---|
| news category | /\/news-category\/(*+)([0-9]+)(category*)?([0-9]+)?/ | /news-category/%text_%id{category%categoryId} | App\Controller\NewsController::listingAction | text,id,text2,categoryId | 1 |

Из-за опциональных параметров приведённый выше пример соответствует следующим URL:
- /news-category/testcategory_12_category_2
- /news-category/testcategory_12
Генерация URL с опциональными параметрами
Исходный url: /some-other-url
path('news category', {
text: 'Test',
id: 67,
categoryId: 33,
getExample: 'some value'
})
Поскольку в шаблоне маршрута нет параметра по умолчанию, вы должны установить все параметры, которые не являются опциональными. Дополнительно есть один параметр, которого нет в обратном шаблоне. Он будет добавлен в URL как обычный GET-параметр.
Результат будет: /news-category/test_67_category_33?getExample=some+value
Добавление значений по умолчанию в маршрут
Вы можете использовать колонку Defaults для добавления значений по умолчанию, которые будут использованы, если вы не укажете параметры в помощнике url.
| ... | Defaults | ... |
|---|---|---|
| ... | text=random text | ... |
path('news category', {
categoryId: 776,
})
Результат будет: /news-category/random+text_5_category_776
Установка языка из маршрута
Symfony поддерживает специальный параметр _locale , который автоматически используется как текущий язык, если он задан через параметры маршрута (см. https://symfony.com/doc/current/translation/locale.html#the-locale-and-the-url).
В качестве примера простой маршрут, соответствующий /{_locale}/test:
| Name | Pattern | Reverse | Controller | Variables | Defaults | Site | Priority | Methods |
|---|---|---|---|---|---|---|---|---|
| myroute | /^\/([a-z]2\/test/ | /%_locale/test | App\Controller\ContentController::testAction | _locale | 1 |
Все, что сопоставлено с _locale, будет автоматически использовано для всего сайта как язык запроса.
Соответствие других параметров с _locale
При миграции существующего сайта на Pimcore 5/6 у вас уже могут быть статические маршруты, которые полагаются на другой параметр (например,language) для определения языка запроса. Чтобы не нужно было мигрировать эти статические маршруты и места, где генерируются маршруты, можно использовать следующую конфигурацию, чтобы сопоставить параметры с _locale. Это сопоставление используется только если для совпавшего маршрута не установлен _locale.
# сопоставит параметр статического маршрута "language" в "_locale"
pimcore:
routing:
static:
locale_params:
- language
Установка приоритетов
Могут быть случаи, когда вы хотите использовать одинаковый шаблон в начале, но в то же время требуются совершенно разные контроллер, действие или дополнительные параметры. В примере ниже видно, когда именно нужно задавать приоритеты; если оставить их пустыми, в зависимости от вашего окружения вы можете столкнуться с необычным поведением, когда один из ваших шаблонов будет полностью проигнорирован. В примере ниже показано, как оба маршрута регулируются приоритетами.
В примере ниже вы можете увидеть, как оба маршрута регулируются приоритетами.
| ... | Pattern | Reverse | Controller | Variables | ... | Priority | Methods |
|---|---|---|---|---|---|---|---|
| ... | //blog/(.+)/ | /blog/%month | App\Controller\BlogController::listAction | month | ... | 1 | |
| ... | //blog/(.+)/(.+)/ | /blog/%month/%id | App\Controller\BlogController::detailAction | month,id | ... | 2 |
Поддержка сайтов
Возможна генерация URL, указывающих на другой сайт внутри Pimcore. Для этого установите опцию Site.
Пример: ссылка на сайт с ID 3
{# используя объект Site #}
{{ path('news', {
id: 4,
text: "some-text",
site: pimcore_site(3)
}) }}
{# используя ID #}
{{ path('news', {
id: 4,
text: "some-text",
site: 3
}) }}
{# используя одно из имён хоста, назначенных сайту #}
{{ path('news', {
id: 4,
text: "some-text",
site: "subsite.example.com"
}) }}
Пример: ссылка обратно на основной сайт
{{ path('news', {
id: 4,
text: "some-text",
site: 0
}) }}
Использование контроллера как сервиса в пользовательских маршрутах
Pimcore поддерживает контроллеры как сервисы в пользовательских маршрутах. Чтобы добавить их, установите в настройке Controller имя вашего сервиса.
Определение сервиса:
services:
app.controller.default:
class: App\Controller\DefaultController
calls:
- [setContainer, ['@service_container']]
Это работает аналогично обратному маршруту: вы можете помещать заполнители прямо в имя контроллера. Следующая конфигурация демонстрирует принцип работы:
| ... | Pattern | Reverse | Controller | Variables | ... | Priority | Methods |
|---|---|---|---|---|---|---|---|
| ... | //default/ | /default | @app.controller.default | month | ... | 10 |
Возврат статуса 404
Иногда вы хотите сгенерировать корректную ошибку 404 внутри вашего контроллера/действия (обрабатываемого пользовательским маршрутом), например, когда запрошенный объект (в маршруте) больше не существует.
Пример:
use \Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
// ...
public function testAction(Request $request): Response
{
$object = DataObject::getById($request->query->getInt('id'));
if( !$object || ( !$object->isPublished() && !$this->editmode) ) {
throw new NotFoundHttpException('Not found');
}
// ...
}
Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.