MODX pdoCrumbs — создание хлебных крошек

pdoCrumbs - создание хлебных крошек в MODX MODX Revo

Сегодня мы реализуем функционал хлебных крошек при помощи сниппета pdoCrumbs который входит в пакет PdoTools. Так же разберемся как внедрить семантическую разметку и как вывести хлебные крошки при помощи шаблонизатора fenom.

Документация по pdoCrumbs

Сниппет для построения навигационных цепочек, в основном используется для создания хлебных крошек. Является лучшей заменой BreadCrumb, работает с документами из любых контекстов и позволяет указывать различные условия для выборки ресурсов.

Сниппет обладает очень высокой скоростью работы, за счет выборки всех нужных элементов из БД за один запрос.

Параметры

Принимает все параметры pdoTools и некоторые свои:

Параметр По умолчанию Описание
&showLog 0 Показывать дополнительную информацию о работе сниппета. Только для авторизованных в контекте «mgr».
&from 0 Id ресурса, от которого строить хлебные крошки. Обычно это корень сайта, то есть «0».
&to Id ресурса для которого строятся хлебные крошки. По умолчанию это id текущей страницы.
&exclude Список id ресурсов, которые нужно исключить из выборки.
&toPlaceholder Если не пусто, сниппет сохранит все данные в плейсхолдер с этим именем, вместо вывода не экран.
&outputSeparator \n Разделитель между крошками
&tpl Имя чанка для оформления ресурса. Если не указан, то содержимое полей ресурса будет распечатано на экран.
&tplCurrent Чанк оформления текущего документа в навигации.
&tplMax Чанк, который добавляется в начало результатов, если их больше чем &limit.
&tplHome Чанк оформления ссылки на главную страницу.
&tplWrapper Чанк-обёртка, для заворачивания всех результатов. Понимает один плейсхолдер: [[+output]]. Не работает вместе с параметром &toSeparatePlaceholders.
&wrapIfEmpty Включает вывод чанка-обертки &tplWrapper даже если результатов нет.
&showCurrent 1 Выводить текущий документ в навигации.
&showHome 0 Выводить ссылку на главную в начале навигации.
&showAtHome 1 Показывать хлебные крошки на главной странице сайта.
&hideSingle 0 Не выводить результат, если он один единственный.
&direction ltr Направление навигации: слева направо «ltr» или справа налево «rtl», например для Арабского языка.

Шаблоны

Шаблон По умолчанию
&tpl @INLINE <li><a href="[[+link]]">[[+menutitle]]</a></li>
&tplCurrent @INLINE <li class="active">[[+menutitle]]</li>
&tplMax @INLINE <li class="disabled">&nbsp;...&nbsp;</li>
&tplHome
&tplWrapper @INLINE <ul class="breadcrumb">[[+output]]</ul>

Официальные примеры

Генерация хлебных крошек для текущей страницы:

[[pdoCrumbs]]

Генерация в ограничением по количеству пунктов:

[[pdoCrumbs?
    &limit=`2`
]]

Сниппет хорошо работает при вызове из pdoResources. Например, вот такой чанк:

<h3>[[+pagetitle]]</h3>
<p>[[+introtext]]</p>
[[pdoCrumbs?
    &to=`[[+id]]`
    &showCurrent=`0`
]]

Официальная русскоязычная документация: https://docs.modx.pro/komponentyi/pdotools/snippetyi/pdocrumbs.

Пример вывода хлебных крошек из практики

Статичный код крошек, у нас такой.

<!-- ======= Breadcrumbs ======= -->
<section class="breadcrumbs">
	<div class="container">
        <ol>
          <li><a href="index.html">Home</a></li>
          <li>Inner Page</li>
        </ol>
        <h2>Inner Page</h2>
	</div>
</section><!-- End Breadcrumbs -->

Ну вернее в одном из уроков мы превратили его в такой:

<!-- ======= Breadcrumbs ======= -->
<section class="breadcrumbs">
    <div class="container">
        <ol>
          <li><a href="/">Главная</a></li>
          <li>[[*pagetitle]]</li>
        </ol>
        <h2>[[*pagetitle]]</h2>
    </div>
</section>
<!-- End Breadcrumbs -->
fenom

<!-- ======= Breadcrumbs ======= -->
<section class="breadcrumbs">
    <div class="container">
        <ol>
          <li><a href="/">Главная</a></li>
          <li>{$_modx->resource.pagetitle}</li>
        </ol>
        <h2>{$_modx->resource.pagetitle}</h2>
    </div>
</section>
<!-- End Breadcrumbs -->

В принципе все хорошо, но нет поддержки уровней выше 3-го, 4-го и т.д. исправим это.

Чтобы не заглядывать в документацию pdoCrumbs, можно взять и перетащить сниппет в место его вывода, увидите окно где можно выбрать и задать нужные параметры, при наведении на них есть подсказки.

Опции pdoCrumb

В конечном итоге у вас должна получится примерно такая секция:

<section class="breadcrumbs">
    <div class="container">
        [[pdoCrumbs?
        	&tpl=`@INLINE <li><a href="[[+link]]">[[+menutitle]]</a></li>`
        	&tplCurrent=`@INLINE <li class="active">[[+menutitle]]</li>`
        	&tplMax=`@INLINE <li class="disabled"> ... </li>`
        	&tplWrapper=`@INLINE <ol>[[+output]]</ol>`
        	&showHome=`1`
        	&hideSingle=`1`
        	&scheme=`full`
        ]]
        <h2>[[*pagetitle]]</h2>
    </div>
</section>
fenom

<section class="breadcrumbs">
    <div class="container">
        {'pdoCrumbs' | snippet : [
        	'tpl' => '@INLINE <li><a href="[[+link]]">[[+menutitle]]</a></li>',
        	'tplCurrent' => '@INLINE <li class="active">[[+menutitle]]</li>',
        	'tplMax' => '@INLINE <li class="disabled"> ... </li>',
        	'tplWrapper' => '@INLINE <ol>[[+output]]</ol>',
        	'showHome' => '1',
        	'hideSingle' => '1',
        	'scheme' => 'full'
        ]}
        <h2>{$_modx->resource.pagetitle}</h2>
    </div>
</section>

Вывод хлебных крошек на всех страницах кроме главной

Удобно для создания универсального шаблона.

И как я говорил ранее внедрять крошки будем в основной шаблон (со сквозными элементами).

Есть несколько вариантов решения данной задачи.

1. Использовать параметр showAtHome=0.

Вся обвертка крошек (она может быть и больше) помещается в tplWrapper, и в вызове указываем  &showAtHome=`0`.

Подходит только для простых крошек, без заголовка страницы как у нас, например если был бы такой код:

<section class="breadcrumbs">
    <div class="container">
        <ol>
            <li><a href="#">Home</a></li>
            <li>Inner Page</li>
        </ol>
    </div>
</section>

То могли его вывести вот так:

[[pdoCrumbs? 
	&tpl=`@INLINE <li><a href="[[+link]]">[[+menutitle]]</a></li>` 
	&tplCurrent=`@INLINE <li class="active">[[+menutitle]]</li>` &tplMax=`@INLINE <li class="disabled"> ... </li>` 
	&tplWrapper=`@INLINE <section class="breadcrumbs"><div class="container"><ol>[[+output]]</ol></div></section>` 
	&showHome=`1` 
	&showAtHome=`0` 
	&hideSingle=`1` 
	&scheme=`full` 
]]

Такое решение  не канает, когда в разметке есть TV или прочие параметры как у нас, т.к. tplWrapper понимает только один плейсхолдер: [[+output]], все остальное будет игнорироваться. Т.е. вот такое: &tplWrapper=`@INLINE <section class="breadcrumbs"><div class="container"><ol>[[+output]]</ol><h2>[[+pagetitle]]</h2></div></section>` не поканает.

2. Вынести весь код в чанк, например breadcrumb и затем воспользоваться модификатором is или if.

[[$[[*id:is=`1`:else=`breadcrumb`]]]]
fenom

{if $_modx->resource.id != 1}{include 'breadcrumb'}{/if}

Помещаем в чанк tpl.

3. Сделать более замороченный вывод pdoCrumbs

Все нашу разметку можно запихать вот в такой вызов:

[[pdoCrumbs?
	&tpl=`@INLINE <li><a href="[[+link]]">[[+menutitle]]</a></li>`
	&tplWrapper=`@INLINE <section class="breadcrumbs"><div class="container">[[+output]]</div></section>`
	&tplHome=`@INLINE <ol><li><a href="[[+link]]">[[+menutitle]]</a></li>`
	&tplCurrent=`@INLINE <li class="active">[[+menutitle]]</li></ol><h2>[[+pagetitle]]</h2>`
	&scheme=`full`
	&hideSingle=`1`
	&showAtHome=`0`
	&showHome=`1`
	&wrapIfEmpty=`1`
]]
fenom

{'pdoCrumbs' | snippet : [
	'tpl' => '@INLINE <li><a href="{$link}">{$menutitle}</a></li>',
	'tplWrapper' => '@INLINE <section class="breadcrumbs"><div class="container">{$output}</div></section>',
	'tplHome' => '@INLINE <ol><li><a href="{$link}">{$menutitle}</a></li>',
	'tplCurrent' => '@INLINE <li class="active">{$menutitle}</li></ol><h2>{$pagetitle}</h2>',
	'scheme' => 'full',
	'hideSingle' => '1',
	'showAtHome' => '0',
	'showHome' => '1',
	'wrapIfEmpty' => '1'
]}

Пример вывода хлебных крошек от bootstrap 5

Их код выглядит так:

Код простых хлебных крошек

А вывод будет таким:

[[pdoCrumbs?
	&tplWrapper=`@INLINE <nav aria-label="breadcrumb"><ol class="breadcrumb">[[+output]]</ol></nav>`
	&tpl=`@INLINE <li class="breadcrumb-item"><a href="[[+link]]">[[+menutitle]]</a></li>`
	&tplCurrent=`@INLINE <li class="breadcrumb-item active" aria-current="page">[[+menutitle]]</li>`
	&showHome=`1`
	&showAtHome=`0`
]]

Семантическая разметка хлебных крошек (BreadcrumbList)

Если вы разрабатываете сайт для себя, то сразу рекомендую заботиться о SEO и внедрить семантическую разметку, она же микроразметка Schema.org. Благодаря ей роботы лучше понимают код и самое главное данная разметка может расширить поисковой сниппет, что повысит его кликабельность.

Пример внедрения микроразметки BreadcrumbList в формате microdata:

[[pdoCrumbs?
	&tplWrapper=`@INLINE <ul class="breadcrumb d-flex justify-content-md-end text-3-5" itemscope itemtype="https://schema.org/BreadcrumbList">[[+output]]</ul>`
	&tpl=`@INLINE <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><a href="[[+link]]" class="text-color-default text-color-hover-primary text-decoration-none"><span itemprop="name">[[+menutitle]]</span></a><meta itemprop="position" content="[[+idx]]"></li>`
	&tplCurrent=`@INLINE <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem" class="active"><span itemprop="name">[[+menutitle]]</span><meta itemprop="position" content="[[+idx]]"></li>`
	&showHome=`1`
]]

pdoCrumbs + schema.org + fenom

{'!pdoCrumbs' | snippet : [ 
    'showHome' => 1, 
    'showAtHome' => 0, 
    'tpl' => '@INLINE <li itemscope="" itemprop="itemListElement" itemtype="http://schema.org/ListItem"><a title="{$menutitle}" itemprop="item" href="{$link}"><span itemprop="name">{$menutitle}</span><meta itemprop="position" content="{$idx}"></a></li>', 
    'tplHome' => '@INLINE <li itemscope="" itemprop="itemListElement" itemtype="http://schema.org/ListItem"><a rel="nofollow" title="{$menutitle}" itemprop="item" href="{$link}"><span itemprop="name">{$menutitle}</span><meta itemprop="position" content="{$idx}"></a></li>', 
    'tplWrapper' => '@INLINE <ol itemscope="" itemtype="http://schema.org/BreadcrumbList" class="breadcrumb">{$output}</ol>', 
    'tplCurrent' => '@INLINE <li itemscope="" itemprop="itemListElement" itemtype="http://schema.org/ListItem" class="active"><a title="{$menutitle}" itemprop="item" href="{$link}"><span itemprop="name">{$menutitle}</span><meta itemprop="position" content="{$idx}"></a></li>' 
]}

Для генерации микроразметки BreadcrumbList Schema.org в формате JSON-LD, поместите в секцию head следующий вызов:

{'!pdoCrumbs' | snippet : [
    'showHome' => 1,
    'tplWrapper' => '@INLINE <script type="application/ld+json">
{
 "@context": "http://schema.org",
 "@type": "BreadcrumbList",
 "itemListElement":
[ {$output} ]
}
</script>'
    'tplHome' => '@INLINE {
   "@type": "ListItem",
   "position": {$idx},
   "item":
   {
    "@id": "{$link}",
    "name": "{$menutitle}"
    }
  },'
    'tplCurrent' => '@INLINE {
   "@type": "ListItem",
   "position": {$idx},
   "item":
   {
    "@id": "{$link}",
    "name": "{$menutitle}"
    }
  }'
    'tpl' => '@INLINE {
   "@type": "ListItem",
   "position": {$idx},
   "item":
   {
    "@id": "{$link}",
    "name": "{$menutitle}"
    }
  },'
]}

Альтернативный вариант, создайте сниппет, например breadSchema, со следующим содержимым.

<?php
$res = $modx->resource;
$site_url = $modx->getOption('site_url');
$site_start = $modx->getOption('site_start') ?: 1;
$ids = $modx->getParentIds($res->id, 10, array('context' => $modx->context->key));
$pids = ($res->id != $site_start) ? [$res->id] : [];
foreach($ids as $id) {
    if($res->id != $id) {
        $pids[] = $id;    
    }
}
$pids = array_reverse($pids);
$output = [];
$index = 0;
foreach($pids as $id) {
    if ($id == 0) {
        $id = $site_start;
    }
    if($res->id != $id) {
        $res = $modx->getObject('modResource', $id);
    }
    
    $uri = $site_url . $res->get('uri');
    if($res->get('id') == $site_start) {
        $uri = $site_url;
    }
    $output[] = '{
        "@type": "ListItem",
        "position": '.++$index.',
        "name": "'.$res->get('pagetitle').'",
        "item": "'.$uri.'"
    }';
}
$wrapper = implode(',', $output);
return '<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": ['.$wrapper.']
}
</script>';

И затем вызываете его в head.

Проверка микроразметки от validator.schema.org, от google и от яндекс.
Если Вам, что-либо непонятно,  спрашивайте в комментариях, обязательно помогу.

В следующем уроке продолжим работать с PdoTools, будем делать меню при помощи сниппета PdoMenu.

Поделиться с друзьями
Алексей

Веб-дизайнер и SEO оптимизатор. Занимаюсь созданием сайтов с 2010 года и их продвижение с 2012 года!

Оцените автора
( 15 оценок, среднее 4.2 из 5 )
Web-Revenue.ru
Добавить комментарий

  1. Руслан

    Здравствуйте, Алексей.

    Если требуется вывести в «крошки» название текущего документа без ссылки, можно использовать следующий код:
    &tplCurrent=`@INLINE [[+menutitle]]`

    Увидел этот пример на другом сайте.

    Ответить
    1. Алексей автор

      Здравствуйте. Можно.

      Ответить
  2. евгений

    добрый день. если использовать этот код pdoCrumbs + schema.org + fenom то в bootstrap 5 крошки выводятся слитно без пробелов и «/» между разделами. как это поправить? там должен быть класс breadcrumb-item. я не пойму куда его вставить в этом чанке

    Ответить
    1. Алексей автор
      <nav aria-label="breadcrumb">
      {'!pdoCrumbs' | snippet : [
          'showHome' => 1,
          'showAtHome' => 0,
          'tpl' => '@INLINE <li itemscope="" itemprop="itemListElement" itemtype="http://schema.org/ListItem" class="breadcrumb-item"><a title="{$menutitle}" itemprop="item" href="{$link}"><span itemprop="name">{$menutitle}</span><meta itemprop="position" content="{$idx}"></a></li>',
          'tplHome' => '@INLINE <li itemscope="" itemprop="itemListElement" itemtype="http://schema.org/ListItem" class="breadcrumb-item"><a rel="nofollow" title="{$menutitle}" itemprop="item" href="{$link}"><span itemprop="name">{$menutitle}</span><meta itemprop="position" content="{$idx}"></a></li>',
          'tplWrapper' => '@INLINE <ol itemscope="" itemtype="http://schema.org/BreadcrumbList" class="breadcrumb">{$output}</ol>',
          'tplCurrent' => '@INLINE <li itemscope="" itemprop="itemListElement" itemtype="http://schema.org/ListItem" class="breadcrumb-item active" aria-current="page"><a title="{$menutitle}" itemprop="item" href="{$link}"><span itemprop="name">{$menutitle}</span><meta itemprop="position" content="{$idx}"></a></li>'
      ]}
      </nav>
      Ответить
  3. Дмитрий

    Добрый вечер Алексей! Хотелось бы увидеть урок или статью про микроразметку shema.org для страницы товара на modX revo SH3???

    Я с хлебными крошками разобрался, все работает, закрывающий тег {div} не поставил!

    Ответить
    1. Алексей автор

      Здравствуйте Дмитрий. Шопкипер мне не особо нравится — сомневаюсь что по нему будут уроки, а вот по minishop2 сделаю уроки — в том числе про внедрение shema.org в карточки товаров

      Ответить
  4. Дмитрий

    Доброе утро!
    Как правильно написать в коде чанка ?
    (код вырезан)

    Ответить
    1. Алексей автор

      У меня в статье хлебные крошки с разметкой 4-го бутстрапа. Вам нужно переделать мой вывод в свой. Был

      &tplWrapper=@INLINE [[+output]]

      ну и оставить его скорее всего нужно таким же, а микроразметку itemscope=»breadcrumb-area» itemtype=»http://schema.org/BreadcrumbList» добавить в обвертку крошек

      Ответить
  5. Дмитрий

    Добрый вечер! Что мне надо в коде поправить?

    Сайт favoritceramica.ru

    Код чанка такой

    [[pdoCrumbs?
        &showAtHome=`0`
        &showHome=`1`
        &exclude=`[[*id:ne=`2`:then=`2`]]`
        &outputSeparator=``
    	&tpl=`@INLINE <a title="[[+menutitle]]" href="[[+link]]" rel="nofollow ugc">[[+menutitle]]</a>`
        &tplHome=`@INLINE <a title="[[+menutitle]]" href="[[+link]]" rel="nofollow ugc">[[+menutitle]]</a>`
    	&tplWrapper=`@INLINE [[+output]]`
    	&tplCurrent=`@INLINE <a title="[[+menutitle]]" href="[[+link]]" rel="nofollow ugc">[[+menutitle]]</a>`
        &tplMax=``
    ]]

    Крошки съежают куда то, как поправить, что бы были на своем месте ?

    Ответить
    1. Алексей автор

      Поправить при помощи CSS. Зашел на ваш сайт все вроде нормально отображается

      Ответить
      1. Дмитрий

        Доброе утро Алексей!

        Я отключил новый чанк, оставил как и есть!

        Ответить
  6. Евгений

    Алексей, здравствуйте.
    а не подскажете как с помощью pdoCrumbs вывести крошки с выпадающим меню (дочерние ресурсы), как здесь например …. вроде должно быть не очень сложно реализовать?

    Ответить
    1. Алексей автор

      Здравствуйте. Не подскажу. Если сделаете поделитесь решением)

      Ответить