Переводим pdoMenu на Fenom
В этой статье я покажу как используя Fenom можно построить многоуровневое меню с помощью pdoMenu с единственным чанком и забыть про 10 шаблонов (tplOuter, tplInner, tpl, tplHere, tplParentRow, tplParentRowHere, tplParentRowActive, tplInnerRow, tplInnerRowHere, tplCategoryFolder).
Материал рассчитан на разработчиков, свободно владеющими навыками программирования на PHP, а также знакомыми со структурой MODX. Желательно знать азы шаблонизатора Fenom. Новички могут использовать данный материал в режиме «Copy/Paste».
Весь процесс снят на видео. Я постарался сделать это максимально просто.
Исходный код
Сниппет
Я не буду публиковать код всего сниппета pdoMenuFenom, а выложу только добавленный функционал. Вы можете вставить его самостоятельно.
$activeResources = $modx->getParentIds($modx->resource->id, 20, ['context' => $modx->context->key]); $activeResources[] = $modx->resource->id; $modx->setPlaceholder('activeResources', array_flip($activeResources)); if (!empty($toArray)) return $tree;
Вставить нужно перед этими строчками (ориентировочно строка 168):
if (!empty($tree)) { $output = $pdoMenu->templateTree($tree); }
Соответственно, при вызове сниппета нужно указать параметр toArray
со значением `1` или true
в зависимости от синтаксиса вызова.
Чанк Menu
{set $ar = $_modx->getPlaceholder('activeResources')} {if $ar[$item['id']]!} {set $classes = $item['id'] == $_modx->resource.id ? 'here' : 'active'} {else} {set $classes = ''} {/if} {if $item['children']?} <li class="tplParentRow {$classes}"> <a href="{$item['id'] | url}">{$item['pagetitle']}</a> <ul class="tplInner"> {foreach $item['children'] as $child} {set $child['level'] = $item['level'] + 1} {$_modx->getChunk('Menu', ['item'=>$child])} {/foreach} </ul> </li> {else} <li class="{$item['level'] > 1 ? 'tplInnerRow' : 'tpl'} {$classes}"> <a href="{$item['id'] | url}">{$item['pagetitle']}</a> </li> {/if}
Вызов в шаблоне
Мы будем работать с шаблоном, в котором вызовем полученный сниппет. Этот шаблон привязывается к ресурсам, у которых должно быть одинаковое меню. Например, это может быть главное вернее меню или меню футера.
<ul class="tplOuter"> {set $items = $_modx->runSnippet('pdoMenuFenom', [ 'parents' => 0, 'displayStart' => true, 'toArray' => true, ])} {foreach $items as $item} {set $item['level'] = 1} {$_modx->getChunk('Menu', ['item'=>$item])} {/foreach} </ul>
Сниппет можно вызывать как кэшированным так и нет. Всё зависит от поставленной задачи.
Внимание!
Чтобы феном работал в шаблонах необходимо включить системную настройку «Использовать Fenom на страницах».
Комментарии ()
Вы должны авторизоваться, чтобы оставлять комментарии.
Удобная реализация, но мне кажется что в pdotools это не попадет )
'menu-fenom' — название моего чанка меню, в котором я разместил код Вашего Чанка Menu
Сделал все по инструкции, только через файловый чанк. Все работает, пока особо не настраивал под себя.
На странице есть два вызова pdoMenu — в верхнем меню (твой вариант) и для вывода нужного контента на самой странице.
Применяю debugParser.
В стандартном вызове pdoMenu для вывода нужного контента на странице в режиме debugParser занимает одно поле и выглядит так:
А верхнее меню (твой вариант), выглядит следующим образом.
Помимо отображения вызова pdoMenu в одном поле:
Ниже идет много полей, в каждом из которых массивы ресурсов (так понимаю, которые должны быть в меню, субменю, субсубменю). То есть получается в debugParser такая простыня из полей с массивами и на выполнение каждого поля уходит от 0.003… до 0.00004… что значительно увеличивает Total parse time
далее идут поля с сформированными ссылками
Подскажи, это так и надо?
Однако я спросил…
Если так и должно быть, то можно еще как-то оптимизировать и не выводить лишние (ненужные) данные. Может фраза «не выводить» неверна, ну я думаю ты меня понял.
Может я путаюсь в терминологии, но я не программист и не очень давно знаком с MODX, прошу строго не судить.
Меня вообще удивляет ситуация, когда люди без опыта устраиваются на работу, получают проекты, а потом везде пишут: «Помогите, сроки горят, я не успеваю/не знаю/, напишите как нужно.» Мне по несколько запросов в месяц таких приходят. Хотите обижайтесь, хотите нет, но у меня по этому вопросу позиция жесткая — ищите халяву в другом месте.
Вы спрашивали — Я ответил. Попробуйте обратиться в сообщество. Возможно там кому-то эта задача покажется интересной.
Подскажи, как лучше исключить определенный ресурс из выборки.
Создал здесь тему
Но советы, данные помогающими, что-то не помогают.
Не нашел ничего лучше как сделать так:
Но так отрабатывает дольше, ведь при каждой итерации идет проверка if $item['id'] !=24
Как еще можно исключить ресурс?
Можно через специальный параметр
не помогает
А вот это помогло:
Благодарю!
Что-то совсем забыл про id, пробовал так:
но так не работает… ступил, признаю...:(
Еще раз благодарю!
Снял флаг в чекбоксе, и сделал так
НО НЕ работает, ресурс НЕ исключается.
А так
вообще пропадает всё меню
Подскажи как реализовать с hideUnsearchable, чувствую так правильнее будет, но как реализовать не знаю.
Этот ресурс должен выводиться в sitemap.xml, но в меню не должен выводиться.
sitemap.xml выводится так:
Вот думаю может с выводом этого сниппета лучше заморочиться?
Только опять не пойму, если поставить чекбокс в «Скрыть из меню», то ресурс 24 не будет выводиться в sitemap.xml
Как тут выйти из ситуации?
Решения.
1. Использовать вариант выше, который работает.
2. Писать условие where одной строкой с правильной группировкой.
docs.modx.pro/komponentyi/pdotools/obshhie-parametryi
Но по факту эта опция не работает в pdoMenu
Да и в других криво работает.
Например, return=data должно возвращать массив. Но возвращается слово «array». И не важно где вызывать сниппет: в php или в fenom.
Для себя проблему кучи чанков решил использованием параметров:
Один раз прописал и не парюсь.
П.С.: Почему то смайлики всегда вставляются в конец, а не там где курсор.
Благодаря вашему методу без проблем ( ну не совсем чтоб на раз два, раза 3 смотрел видео, разбирался с fenom ) реализовал нужное и теперь вообще прям не боюсь этих менюшек )