Перейти к основному содержимому

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, а также возможно определить опциональную часть: чтобы сделать часть необязательной, просто заключите её в фигурные скобки (см. пример ниже).

NamePatternReverseControllerVariablesDefaultsSite IDsPriorityMethods
news category/\/news-category\/(*+)([0-9]+)(category*)?([0-9]+)?//news-category/%text_%id{category%categoryId}App\Controller\NewsController::listingActiontext,id,text2,categoryId1

Сетка с новым маршрутом

Из-за опциональных параметров приведённый выше пример соответствует следующим 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:

NamePatternReverseControllerVariablesDefaultsSitePriorityMethods
myroute/^\/([a-z]2\/test//%_locale/testApp\Controller\ContentController::testAction_locale1

Все, что сопоставлено с _locale, будет автоматически использовано для всего сайта как язык запроса.

Соответствие других параметров с _locale

При миграции существующего сайта на Pimcore 5/6 у вас уже могут быть статические маршруты, которые полагаются на другой параметр (например,language) для определения языка запроса. Чтобы не нужно было мигрировать эти статические маршруты и места, где генерируются маршруты, можно использовать следующую конфигурацию, чтобы сопоставить параметры с _locale. Это сопоставление используется только если для совпавшего маршрута не установлен _locale.

# сопоставит параметр статического маршрута "language" в "_locale"  
pimcore:
routing:
static:
locale_params:
- language

Установка приоритетов

Могут быть случаи, когда вы хотите использовать одинаковый шаблон в начале, но в то же время требуются совершенно разные контроллер, действие или дополнительные параметры. В примере ниже видно, когда именно нужно задавать приоритеты; если оставить их пустыми, в зависимости от вашего окружения вы можете столкнуться с необычным поведением, когда один из ваших шаблонов будет полностью проигнорирован. В примере ниже показано, как оба маршрута регулируются приоритетами.

В примере ниже вы можете увидеть, как оба маршрута регулируются приоритетами.

...PatternReverseControllerVariables...PriorityMethods
...//blog/(.+)//blog/%monthApp\Controller\BlogController::listActionmonth...1
...//blog/(.+)/(.+)//blog/%month/%idApp\Controller\BlogController::detailActionmonth,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']]


Это работает аналогично обратному маршруту: вы можете помещать заполнители прямо в имя контроллера. Следующая конфигурация демонстрирует принцип работы:

...PatternReverseControllerVariables...PriorityMethods
...//default//default@app.controller.defaultmonth...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');
}

// ...
}


Вы можете предложить улучшение документации или задать вопрос в комментариях.
Если вам нужна полноценная консультация — вы можете заказать её на нашем сайте.