DLBuildMenu: параметры и шаблоны (документация)



Сниппет вывода меню DLBuildMenu, основанный на DocLister, предоставляет мощные инструменты создания меню сайта на MODx Evo. Но многие, даже опытные, MODx-юзеры его не применяют из-за отсутствия документации. Восполняю этот пробел.


Уровень статьи: для начинающих


Краткое описание

DLBuildMenu — сниппет для вывода меню сайта на MODx Evolution. Построен на основе ДокЛистера, по сути этосниппет-обертка с вызовом DocLister внутри — поэтому в нём можно использовать практически все параметры и фишки самого DocLister.

Применяя prepare, мы получаем неограниченные возможности подготовки данных. А развитая система шаблонизации ДокЛистер, дополненная в DLBuildMenu новыми параметрами, даёт в руки, на мой взгляд, даже чрезмерно богатый инструментарий.

Разработчик: Agel_Nash

Зависимости и требования

  • Для работы DLBuildMenu у вас должен быть установлен DocLister (есть в последних релизах MODx Evo по умолчанию).
  • Требуется PHP не ниже версии 5.3

Установка

  • DLBuildMenu входит по умолчанию в новую кастомную сборку MODx Evo 1.2.1-d9.1.2 от 21.03.2017.
  • На более старых кастомных сборках и на официальной сборке для его установки нужно установить или переустановить ДокЛистер из Extras, при этом нужно, чтобы DLBuildMenu был отмечен галочкой в списке при установке.

Файлы

  • assets/snippets/DocLister/snippet.DLBuildMenu.php
  • assets/snippets/DocLister/lib/DLFixedPrepare.class.php (метод buildMenu)

Преимущества

  • есть возможность применения prepare для обработки данных перед выводом.
  • богатый выбор способов задания шаблонов, в том числе инлайн-шаблоны.
  • сортировка по TV-параметрам с приведением к нужному типу.
  • может делать фильтрацию по TV-параметрам.
  • можно придумывать и задавать собственные параметры и обрабатывать их в prepare.

Кроме того, в DLBuildMenu работают и другие фишки из арсенала ДокЛистер, описывать которые здесь не стану, для этого нужно изучать сам DL.

Параметры

Базовые параметры

&idType (hardcoded)
Тип выборки аналогично DocLister.

Возможные значения: parents
Примечание: значение параметра &idType жестко записано в коде как parents.

&parents
Родительская (начальная) папка.

Возможные значения: список ID родителей через запятую.
Значение по умолчанию: 0
Примечание: Обратите внимание, что значение &parents по умолчанию равно 0, что означает «выводить начиная с корня сайта». Это отличается от дефолтного значения &parents параметра в ДокЛистере.

& currentDepth
Исходный уровень вложенности (глубина).

Возможные значения: целое число от 1 и больше.
Значение по умолчанию: 1
!!! В название параметра пришлось вставить пробел после "&" — иначе здешний парсер вырезает.

&maxDepth
Макс. глубина

Возможные значения: целое число от 1 и больше.
Значение по умолчанию: 5

&BeforePrepare и &AfterPrepare
Обработка данных через prepare аналогично DocLister.

Возможные значения: задаются по правилам ДокЛистера. Могут быть списком имен сниппетов и вызовов методов ранее загруженных классов, либо анонимной функцией.
Примечание: для prepare в DLBuildMenu уже имеется встроенный обязательный вызов DLFixedPrepare::buildMenu. Обработчики из &BeforePrepare вызываются перед встроенным, из &AfterPrepare — после встроенного вызова.

&activeClass
CSS-класс активного (текущего) пункта меню и его родительских элементов всех уровней.

Возможные значиения: Имя CSS-класса, или несколько имён CSS-классов, заданные как в HTML-теге (через пробел).
Значение по умолчанию: active
Примечание: этот класс и этот параметр существуют в дополнение к уже имеющимся в ДокЛистере классам first, last, odd, even и current (см. документацию по DocLIster).

Параметры условий выборки

&addWhereList
Условия выборки документов для всех уровней.

Возможные значения: задаются как в DocLister (по правилам MySQL для условия WHERE).
Значение по умолчанию: c.hidemenu = 0

&addWhereListN
Условия выборки документов N-го уровня, для соответствующих уровней &addWhereListN имеет приоритет над &addWhereList.

Возможные значения: задаются по правилам MySQL для условия WHERE.
Значение по умолчанию: нет
Примечание: Если &addWhereListN не задан, для всех уровней используется &addWhereList.

Параметры сортировки

&orderBy
Условия сортировки документов всех уровней.

Возможные значения: задаются как в DocLister (по правилам MySQL для ORDER BY).
Значение по умолчанию: menuindex ASC, id ASC

&orderByN
Условия сортировки документов N-го уровня вложенности, для соответствующих уровней &orderByN имеет приоритет над &orderBy.

Возможные значения: задаются по правилам MySQL для ORDER BY.
Значение по умолчанию: нет
Примечание: Если &orderByN не задан, для всех уровней используется &orderBy.

Параметры «Список TV»

&tvList
Список TV-параметров, которые участвуют в выборке (как в DocLister).

Возможные значения: список имён TV-параметров через запятую.
Значение по умолчанию: нет

&tvListN
Список TV-параметров в выборке для N-го уровня вложенности, для соответствующих уровней &tvListN имеет приоритет над &tvList.

Возможные значения: список имён TV-параметров через запятую.
По умолчанию: пусто.
Примечание: Если &tvListN не задан, для всех уровней используется &tvList.

Шаблоны

Шаблоны DLBuildMenu задаются по правилам DL, то есть могут быть и инлайн-шаблонами, и именами чанков, или загружаться из файла, из документа MODx, из конфига, из глобального плейсхолдера.

Шаблоны-обёртки

&TplMainOwner
Основной шаблон-обертка.

Значение по умолчанию:
@CODE:<ul id="nav" class="menu level-1">[+dl.wrap+]</ul>

Примечание: у вас должен быть задан шаблон &TplMainOwner или &TplOwner1, иначе будет использовано дефолтное значение шаблона &TplMainOwner.

&TplSubOwner
Шаблон-обертка для вложенных уровней (для субменю).

Значение по умолчанию:
@CODE:<ul class="sub-menu level-[+dl.currentDepth+]">[+dl.wrap+]</ul>

Примечание: для вывода N-уровневого меню у вас в дополнение к основной обёртке должен быть задан по крайней мере &TplSubOwner и/или шаблоны &TplOwnerN. Иначе будет использовано дефолтное значение &TplSubOwner.

&TplOwnerN
Шаблон-обертка для субменю N-го уровня вложенности, для соответствующих уровней &TplOwnerN имеет приоритет над &TplMainOwner и &TplSubOwner (см. Примечание).

Значение по умолчанию: нет
Примечание: Если заданы и &TplOwner1, и &TplMainOwner, то будет использован &TplOwner1. Если заданы и &TplOwner2 и &TplSubOwner, то для уровня 2 будет использован &TplOwner2, а для уровней начиная с 3-го — &TplSubOwner.

Шаблоны пункта меню

&TplOneItem
Основной шаблон для каждого пункта меню всех уровней.

Значение по умолчанию:
@CODE:<li id="menu-item-[+id+]" class="menu-item [+dl.class+]">
   <a href="[+url+]" title="[+e.title+]">[+title+]</a>
   [+dl.submenu+]
</li>

Примечание: у вас должны быть заданы все нужные вам шаблоны пунктов меню, по крайней мере &TplOneItem. Иначе для пунктов, у которых шаблон не определен вами, будет использовано дефолтное значение &TplOneItem.

&TplDepthN
Шаблон пункта меню вложенности N, для соответствующих уровней &TplDepthN имеет приоритет над &TplOneItem.

Значение по умолчанию: нет
Примечание: Например, если задан &TplDepth3, он заменит собой шаблон &TplOneItem на 3-м уровне вложенности.

Шаблоны пункта без дочерних элементов

&noChildrenRowTPL
Основной шаблон пункта меню без дочерних элементов для всех уровней.

Значение по умолчанию: нет

&TplNoChildrenDepthN
Шаблон пункта меню без дочерних элементов вложенности N. Для соответствующих уровней &TplNoChildrenDepthN имеет приоритет над &noChildrenRowTpl.

Значение по умолчанию: нет
Примечание: если для пункта меню не задан ни &noChildrenRowTPL, ни &TplNoChildrenDepthN, то в качестве шаблона для «бездетных» пунктов будет использован шаблон, заданный вами в других параметрах (&TplOneItem или &TplDepthN).

Шаблоны текущего пункта
&TplCurrent
Шаблон текущего пункта меню с дочерними, имеет приоритет перед всеми шаблонами пунктов меню, кроме &TplCurrentN.

Значение по умолчанию: нет

&TplCurrentN
Шаблон текущего пункта меню вложенности N с дочерними, для N-го уровня шаблон &TplCurrentN имеет приоритет перед всеми шаблонами пунктов меню с дочерними, включая &TplCurrent.

Значение по умолчанию: нет.

&TplCurrentNoChildrenN
Шаблон текущего пункта меню без дочерних элементов, где N — номер уровня вложенности. Для уровня N имеет приоритет перед любыми другими шаблонами «бездетных» пунктов меню.

Значение по умолчанию: нет.

Плейсхолдеры

Основные плейсхолдеры

[+dl.wrap+]
С его помощью в шаблон-обёртку подставляется сформированный HTML-код меню/субменю для вывода.

Примечание: используется только для шаблонов-обёрток &TplMainOwner, &TplSubOwner и &TplOwnerN.

[+dl.submenu+]
Сюда подставляется сформированный HTML-код субменю вместе с шаблоном-обёрткой.

Примечание: используется для шаблонов пункта меню, как не текущих, так и текущих.

[+dl.currentDepth+]
Текущий уровень вложенности (текущая глубина).

Примечание: обратите внимание, что отсчёт текущего уровня вложенности (текущей глубины) начинается с 1.

[+dl.class+]
Работает так же, как и в DocLister, автоматически добавляя классы last, first, current, even, odd соответственно для последнего, первого, текущего, четного и нечетного пункта. Кроме того, добавляет класс active для текущего элемента и родительских элементов всех уровней текущего элемента.

Примечание: классы last, first, current, even, odd и active могут быть переопределены в параметрах &lastClass, & currentClass, &firstClass, &evenClass, &oddClass и &activeClass.
!!! В название параметра & currentClass пришлось вставить пробел после "&" — иначе здешний парсер вырезает.

[+url+]
УРЛ ресурса аналогично ДокЛистеру.

[+e.title+]
Экранированное значение menutitle или pagetitle (если menutitle пуст) аналогично Доклистеру.

[+id+]
ID ресурса аналогично ДокЛистеру.

Другие плейсхолдеры из DocLister

Вы можете использовать и другие плейсхолдеры ДокЛистера, устанавливаемые контроллером site_content и различными экстендерами.

Например:
  • плейсхолдеры TV-параметров вида [+tv_prefix.tv_name+],
  • плейсхолдеры экранированных значений вида [+e.field_name+],
  • плейсхолдер [+date+] и другие.

Для получения более подробной информации по плейсхолдерам ДокЛистера, по экстендеру e (экранирование) и другим возможностям см. документацию к DocLister.



Более полная статья по DLBuildMenu — на моем сайте, там в конце материала есть еще «Таблица приоритетов шаблонов» (здешний редактор не создает таблиц).

Вопросы можете задавать и здесь и там.

55 комментариев

avatar
Спасибо, тебе, человечище!!! Это именно то, чего не хватало многим, жму плюс!
avatar
Времени кучу потратил, в основном на оформление блин :)

Скоро будет еще пара статей по DLBuildMenu с примерами и другой ценной информацией, и тема будет полностью раскрыта :)
Комментарий отредактирован 2017-03-29 09:45:15 пользователем Harand
avatar
как наберется больше материала — при желании можете закинуть на http://docs.evolution-cms.com. Все же удобнее будет, если весь материал будет в одном месте =)
ну и для любых доков — фреймворка, языка программирования и т.д. наличие примеров все же маст хев, уже для вашей статьи их не хватает
avatar
На docs.evolution-cms.com обязательно закину — вопрос только в наличии времени.

Примеры будут в следующих статьях по DLBuildMenu, вот я в предыдущем комменте написал:

Скоро будет еще пара статей по DLBuildMenu с примерами и другой ценной информацией, и тема будет полностью раскрыта :)

А потом то же самое проделаю по некоторым другим сниппетам из набора DocLister: DLcrums и так далее.

Надо популяризировать нововведения Эво :)
Комментарий отредактирован 2017-03-29 10:31:35 пользователем Harand
avatar
Вчера как-раз решил испробовать и с сожалением отметил, что параметр &documents с соответсвующим idTypes=`doucments` — не действует. Надо было сформировать меню в футере в один уровень по документам, выбранным через tv с типом selector.
avatar
Да, у меня как раз в самом начале отмечено:
Примечание: значение параметра &idType жестко записано в коде как parents.

Специально внес это в список параметров, чтобы люди зря не пытались :)
avatar
Исходя из array_merge и того, что массив с idTypes и parents вынесен перед массивом $p — я подумал, что можно это поведение изменить. Но оно, почему-то, не изменилось :)
avatar
avatar
Линейное меню проще формировать через DocLister
avatar
Кстати, да.
avatar
Я в итоге так и сделал :)
avatar
Блин, в запарке не указал разработчика, нехорошо :) сегодня исправлюсь.
avatar
Хорошо описано. Юзать не буду просто по причине того, что не вижу, где бы мне это пригодилось. Wayfinder для 99% моих задач достаточно. Иногда через DocLister делаю.
avatar
А вы попробуйте вывести через Wayfinder меню в 3-4 уровня с разными шаблонами на каждом уровне:)
Или когда нужно выводить еще и ТВ ))
Или когда у вас документов больше 10 000 ))

Вот тогда и увидите значительные преимущества. Собственно так как DLBulidMenu перекрывает все возможности Wayfinder и нет минусов по сравнению Wayfinder поэтому на него и логично переходить
avatar
Так это бесспорно, просто мне не нужно.

Меня вот что интересует — в чем логика сниппетов, которые должны прийти на замену старым, но в дефолтовых обертках используют крайне специфичную верстку, которая со старой не совпадает ни по виду, ни по логике. Не проще ли все эти заковырки вынести в несколько конфигов по умолчанию. Примерно как у того же Breadcrumbs
Комментарий отредактирован 2017-03-30 13:30:59 пользователем alexbeep
avatar
плюсанул) то чего не хватало для избавления от wayfinder

вопрос: как обстоят дела с количеством запросов в сравнении с wayfinder?
avatar
Если не забивать на значение параметра maxDepth, то все хорошо.
avatar
допустим у меня в шапке 1 меню в два уровня
и внизу ещё два 2 меню с выборкой нужных документов) при wayfinder сразу +100 запросов, может я параноик, но хочется меньше))
avatar
давайте так, вы для начала попробуйте и сообщите результаты — думаю это будет интересно всем;-) Если что не так, показыайте вызовы одного и другого — обсудим как оптимизировать. Сейчас же это обсуждение абстрактного коня в вакуме.
avatar
окей) переведу один сайт на этот сниппет и сравним :) может просто паранойя
avatar
Замечу что если используется AliasListingFolder то Wayfinder генерит очень много лишних запросов а вот DLBuilMenu ведет себя адекватно.
avatar
Это кстати уже не так сильно влияет после последних комитов )
avatar
Видел этот коммит )
avatar
Дополнил материал:
— Добавил подраздел Плейсхолдеры
— Уточнил описания шаблонов &TplMainOwner, &TplSubOwner, &TplOneItem

Писал быстро, если заметите какие-либо ошибки/очепятки, пишите в комментах.
avatar
проверка показала, что для вложенных меню, лучше использовать всё таки Wayfinder, либо его кастомизацию для правильного отображения tv параметров.
Чтобы не быть голословным, добавил два вызова сниппетов, документов около 50.

[!DLBuildMenu?
&parents=`0`
!]

[!Wayfinder?
&startId=`0`
!]


и итоге получилось
DLBuildMenu (182.01 ms)
Wayfinder (6.00 ms)

выводы очевидны
  • 64j
  • +1
avatar
провёл аналогичный тест, с глубиной до 2 уровня. 24 документа.
DLBuildMenu делает 12 запросов и отдает за 0.08 — 0.1сек
Wayfinder делает 5 запросов и кушает на 2 мегабайта меньше, отдает за 0.050 — 0.059сек
avatar
Если взялся проверять то 1 выборка это не результат:

50 документов
500 документов
5000 документов

вывод в несколько уровеней
вывод с ограниченным числом уровней
вывод с ТВ

вот тогда будет ясна разница:)

банально с включенной aliasListingFolder Wayfinder генерит + 500 лишних запросов как минимум а я его включаю если документов больше 5-10к
avatar
aliasListingFolder сомнительная штука) я уже включал, где-то нормально работает, где-то показывает урл родителя (если он выключен)
avatar
Потому как писал что при AliasListingFolder нельзя выключать последнего родителя из URL ) иначе возможны проблемы
а так это единсвенный путь запустить сайт с 30 000 и более товарами )
avatar
Я тут обещался сделать по DLBuildMenu статью с примерами. Она почти сделана, но пришла идея примеры эти протестить на скорость на разного объема выборках, как раз как ты написал.

Так что, как появится немного времени — выложу с результатами тестов.

Единственное — что я aliasListingFolder никогда еще не пользовался. Где-то есть по нему доки?
avatar
Просто галочка в настройках в ЧПУ и все:)
avatar
Я имею в виду, механизмы его действия, на что он влияет, возникающие нюансы.

Вот один нюанс уже вижу в предыдущих комментах.
avatar
Это единсвенный нюанс
а так логика работы он исключается все документы не папки их AliasListing чем существенно его уменьшает
увеличивая скорость работы есть топик от меня уже блольше года назад там про ограничение в 10000 документов вообщем ищиться легко там описано откуда ноги растут.

Логично использовать если документов больше 5к
иначе выигрыша нет
avatar
Спасибо, нашел.
avatar
Wayfinder может и не генерить эти 500 лишних запросов)))

За основу взят оригинальный с небольшой доработкой, плюс использование разных шаблонов на разных уровнях
https://github.com/64j/Wayfinder_custom
avatar
Чего вы привязались к этому aliasListingFolder. Он убирает из карты только конечные ресурсы, если их много (а это обычно новости или товары) — то вряд ли кто-то их все выводит в меню с помощью Wayfinder-а :) Обычно в меню папки-каталоги ну и пару текстовых страниц, так что вряд ли в формировании меню этот aliasListingFolder вообще имеет какое-то критическое значение. Его основная задача — не дать распухнуть кэшу aliasListing — который при ресурсах более 5 000 начинает жрать много памяти. Т.к. папок более 5 000 бывает редко, то за счет этого и живем, но к меню это имеет весьма посредственное отношение.
avatar
Чего вы привязались к этому aliasListingFolder.

Мы к нему не привязывались. Мы его просто обсуждаем.

А документы-не-папки могут выводиться, например, при создании через WF или DLBuildMenu карты сайта.
avatar
Не встречал на новостных сайтах или больших каталогах (более 5 000 ресурсов) вывода карты сайта со всеми этими ресурсами. Обычно там тоже ограничиваются выводом папок :)
avatar
Согласен, в большинстве случае это так. Пока нет времени, появится — я обязательно потестирую и WF, и DLBuildMenu на разных реальных примерах, результаты опубликую.
avatar
А как вывести строчку «Атрибуты ссылки» в WF было [+wf.attributes+]
пробую [+e.link_attributes+], но DLBuildMenu не выводит ничего.
P.S. Удобно выводить иконку к меню через данный пункт.
Комментарий отредактирован 2017-04-18 11:42:06 пользователем JoniDES
avatar
А как именно у вас задается иконка? и зачем e?
avatar
Иконку задаю просто прописав в строке: (подключен font-awersome)
можно было бы еще подключить согласно классу и менять через css иконку через background но так дольше!

E — взял из статьи (документации)
[+e.field_name+] (где field_name — это имя поля таблицы site_content)

avatar
e — это экранирование, оно не всегда нужно. А нужно, например, для тега

<a title="[+e.title+]" href="[+url+]"></a>


чтобы в title кавычки не поломались.
Комментарий отредактирован 2017-04-19 17:42:27 пользователем Harand
avatar
вот только почему-то в шапке про это не сказано, а телепат с меня пока не очень :)
avatar
В шапке сказано
Кроме того, в DLBuildMenu работают и другие фишки из арсенала ДокЛистер, описывать которые здесь не стану, для этого нужно изучать сам DL.

e — это как раз из тех фишек.
avatar
Перепишу последний абзац, чтобы понятнее стало.
avatar
попробуйте просто [+link_attributes+]
avatar
О спасибо — так работает, что-то я не додумался так попробовать :)
avatar
У меня DLBuildMenu не подхватывает конфиг, если вызывать так — [[DLBuildMenu? &config=`menu`]]
avatar
&config=`menu:custom`

и сам конфиг menu.json лежит в папке DocLister/config/custom
avatar
Так тоже не работает.
К тому же судя по коду DocLister'а, это тоже самое:
github.com/AgelxNash/DocLister/blob/master/assets/lib/Helpers/Config.php#L51

Конфиг лежит в папке DocLister/config/custom, все верно.

К слову, вызов [[DocLister? &config=`menu`]] отрабатывает нормально.
avatar
У меня подобное на OpenServer под Виндой 7, а на хостинге всё работает.

Разбираться в причинах пока, увы, некогда.
Комментарий отредактирован 2017-06-18 14:01:57 пользователем Harand
avatar
Дело было в порядке обработке параметров.
avatar
А issue/PR не отправляли на GitHub?
avatar
Отправлял
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.