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

Создавать динамическое меню в MODX мы будем при помощи сниппета PdoMenu из пакета pdoTools . Перед тем как начать ознакомьтесь с основной документацией.

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

Параметры

Параметры шаблонов

Параметры CSS классов

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


официальную документацию можете почитать здесь . А сейчас разберем самые типовые вызовы меню.

Вызов PdoMenu

Вариант 1 . На месте этого статического меню вызовем сниппет pdoMenu , для этого в дереве ресурсов, на вкладке “Элементы ” в разделе сниппеты разверните ветку pdoTools , далее нажмите на pdoMenu левой кнопкой мыши (не отпускайте кнопку) и перетащите этот сниппет в место, где вы хотите вызвать меню, далее в открывшемся окошке заполните необходимые параметры и нажмите «Сохранить «.

Вариант 2 . Просто вручную пишем вызов.

Типовые примеры

Обычное одноуровневое меню

К примеру у нас самое обычное меню, со следующей html разметкой.

Получился вот такой код с вызовом меню:

  • &parents=`0` — список родителей (в моем случае я не ограничиваю выборку, так как я все равно выведу только определенные страницы);
  • &level=`1` — уровень вложенности (в данном случае ее нет);
  • &resources=`2,3,4,5` — список ресурсов которые нужно вывести в меню;
  • &firstClass=`0` — класс для первого пункта меню (не какого);
  • &lastClass=`0` — класс последнего пункта меню (не какого);
  • &outerClass=`top-menu` — класс обертки меню (подставляется в ul);
  • &hereClass=`current-menu-item` — класс для активного пункта меню (подставляется в li);
  • &rowClass=`menu-item` — класс одной строки меню (подставляется в li).

Двухуровневое кастомное bootstrap меню

Статический html код выглядит так:

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

Так же в следующем уроке я приведу еще пару выводов выпадающих меню, на основе bootstrap ( и , это для тех кто не уловил суть. Ну а далее сделаем .

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

Вы можете изменить верхнее меню панели управления MODX или поменяв порядок следования элементов, или спрятав некоторые из них от определенных пользователей. Вы также можете добавить новые пункты к существующим или персональным действиям, которые вы создаете. Далее мы вначале рассмотрим методы, используемые для модификации верхнего меню, а затем некоторые практические примеры.

Концепции верхнего меню

Система меню в Revolution имеет совершенно новую архитектуру. Она почти не имеет ничего общего с системой меню Evolution за исключением названий некоторых пунктов. Для настройки меню не обязательно понимать новую систему меню, но это понимание помогает в работе, особенно если вы собираетесь создавть Персональные страницы панели управления, доступ к которым будет выполняться через меню.

Дерево верхнего меню

Перейдите к разделу верхнего меню Система -> Действия и вы увидите основы системы меню. Дерево справа (Верхнее меню) содержит действительные элементы меню и подменю. Если вы раскроете различные разделы, то вы увидите, что это точная копия верхнего меню. Элементы верхнего уровня - это то, что вы видите в верхней части панели управления. Почти всегда это контейнеры для подменю. Каждое подменю в дереве соответствует действию в панели управления. Когда вы кликаете на подменю, в панели управления выполняется действие (например, очистка кэша сайта или переход к панели управления доступом). Фактически и пункты верхнего меню могут быть действиями, но ни один из пунктов верхнего меню не сконфигурирован таким образом.

То, что происходит, когда вы кликаете на элементе меню, фактически определяется здесь. Как вы увидите, вы можете легко переопределить то, что происходит при клике на пункте меню, а также можете переименовать, спрятать или удалить элементы списка меню. Вы также можете добавить элементы в меню и задать, что произойдет при клике на них. Фактически вы можете создать полностью новую систему меню для панели управления, которая заменит существующую и различные пользователи могут видеть различные меню. Все это можно делать без изменения ядра MODX.

Физическое отображение меню также задается здесь. Это не совпадение, что все элементы меню расположены в том же порядке, как они располагаются в верхнем меню. Если вы переместите их в дереве, верхнее меню также изменится при перезагрузке страницы.

Рассмотрим некоторые действия панели управления, но будьте осторожны, чтобы не изменить их - нажимайте кнопку "Отменить" после их просмотра.

В расположенном справа дереве (Верхнее меню) кликните правой кнопкой на пункте "Сайт" и выберите в выпадающем меню пункт "Редактировать". Появится диалоговое окно Редактирования с полями, которые определяют действие меню:

Имя - имя элемента меню

Описание - описание элемента меню

Действие - спецификация PHP-файла, который будет выполнен

Значок - дополнительный значок для пункта меню

Параметры - необязательные параметры $_GET для URL

Обработчик - JS код, который будет выполнен

Права доступа - разделенный запятыми список необходимых прав доступа

Отметим, что большинство полей пункта "Сайт" пустые. Это потому, что это контейнер для подменю, находящихся в нем. Если вы кликните на меню "Сайт" в верхнем меню, ничего не происходит.

Давайте посмотрим на подраздел меню, который что-то делает. Кликните на "Отмена" для завершения диалога, раскройте раздел "Сайт" дерева правой панели, кликните правой кнопкой на подменю "Обновить сайт" и выберите "Редактировать".

Отметим, что в открывшемся диалоговом окне имеется содержимое полей "Обработчик" и "Права доступа". Поле "Права доступа" говорит нам, что пользователь не может выполнить действие этого подпункта меню, если у него нет права доступа empty_cache. В поле "Обработчика" находится реальный код JS, который выполняется, когда вы выбираете этот подпункт. Все пункты, в которых действительно выполняются какие-то действия имеют заполненными поля или "Действие", или "Обработчик". Если заполнено поле "обработчик", то исполняется код, расположенный в этом поле, а поле "Действие" игнорируется. Если поле "Обработчик" не заполнено, то выполняется действие из поля "Действие". Поле "Действие" обычно является указателем или на файл-контроллер, или на одно из действий в дереве "Действия", расположенного слева (которые собственно указывают на соответствующие файлы-контроллеры). Закройте диалог, нажав кнопку "Отменить".

Давайте посмотрим на вариант пункта меню с действием. Загрузите и установите через Управление пакетами дополнение Batcher, перезагрузите страницу и снова зайдите в раздел Система -> Действия . В разделе "Компоненты" в правом дереве (раскройте его, если необходимо) кликните правой кнопкой на Batcher и выберите "Редактировать". Теперь мы видим заполненное поле "Действие, а не "Обработчик" : batcher - index. Завершите диалог редактирования, нажав кнопку "Отмена".

В левой панели все пункты верхнего уровня являются пространствами имен. В дереве "Действия" слева раскройте пространство имен "batcher". Вы должны увидеть действие index. Это действие, на которое указывает меню Batcher, которое мы видели на правой панели.

Рассмотрим, что мы можем делать с деревом "Верхнее меню". Элементы в дереве "Верхнее меню" могут быть перераспределены путем их перетаскивания. Если вы меняете местоположение пункта меню в дереве, также поменяется и фактическое верхнее меню, хотя для того, чтобы это увидеть, вам нужно будет перезагрузить страницу панели управления.

Для добавления пункта в верхнее меню вы можете кликнуть правой кнопкой где-нибудь в области дерева и выбрать "Добавить пункт меню". Для добавления пункта в меню верхнего уровня вы также можете нажать кнопку "Добавить пункт".

Пункты меню могут быть удалены путем клика на них правой кнопкой и выбора пункта "Удалить". Если вы удалите пункт меню, содержимое его полей будет утрачено также будут удалены любые дочерние элементы. Это действие необратимо.

Если вы хотите убрать пункт меню без фактического его стирания (почти всегда это лучший вариант действий), вы можете спрятать его, поместив что-нибудь в поле "Права доступа". Если в этом поле уже что-то находится, добавьте запятую и имя нового права доступа. Пока этим правом доступа будет право доступа, которого ни у кого нет, пункт меню будет невидимым. Вы сможете сделать его опять видимым, путем удаления добавленного права доступа. Если вы хотите показывать определенный пункт меню, определенным пользователям (но не всем), просто создайте шаблон новой политики, содержащий только пользовательские права доступа, создайте новую политику, основанную на этом шаблоне, и создайте запись запись контекстного списка управления доступом, которая применяется к этим пользователям и присвойте эту политику.

Для изменения заголовка верхнего меню, уточните его описание. Затем перейдите в раздел меню Система-> Управление словарями. Выберите пространство имен "core" и тему "topmenu". Выпадающий список тем содержит более одной страницы, поэтому вам может потребоваться перейти ко второй странице, чтобы найти тему "topmenu". Найдите языковую строку для нужного элемента меню, дважды кликните на ее значении и измените ее. Любые изменения, которые вы выполните здесь, будут действовать и после обновления версии MODX и после обновления любой из компонент сторонних разработчиков.

Описанный выше метод будет работать только для встроенных в ядро пунктов меню. Для элементов меню сторонних разработчиков потребуется выбрать соответствующее пространство имен. Например, если вы хотите изменить соответствующий пункт меню для Batcher, вам нужно будет изменить значение строки управления словарями для пространства имен batcher.

Дерево "Действия"

Вернитесь к разделу Система -> Действия , если вы из него вышли. В левой панели кликните на действии "index" ниже имени "batcher" и выберите в выпадающем списке "Редактировать". Напомним, что это действие, на которое указывает элемент меню Batcher на правой панели. Вы увидите, что контроллером для этого действия будет index, а пространство имен batcher. Если мы сейчас перейдем в раздел Система->Пространство имен , мы увидим, что путем для пространства имени batcher будет:

{core_path}components/batcher

С привязкой к контроллеру, который будет выполняться при клике на этом пункте меню, MODX создаст полный путь, подобный этому:

путь_пространства_имен + имя_контроллера +.php

Другими словами, полагая, что core находится в месте по умолчанию, MODX инициирует выполнение файла-контроллера по адресу:

core/components/batcher/index.php

Если вы посмотрите на этот файл, то вы увидите, что он как раз содержит файл index.php в каталоге core/components/batcher/controllers, который загружает класс Batcher и инициализирует его, запуская Batcher в панели управления. Мы создадим новый пункт меню в разделе "Компоненты" немного позже, когда будем создавать пользовательские страницы панели управления.

Многие элементы меню в правой панели не имеют активных действий, показываемых в левой панели. Это происходит потому, что пути к их файлам-контроллерам хранятся в базе данных MODX и не должны редактироваться (по крайней мере это сделать сложнее). Эти пути хранятся в таблице modx_actions. Каждое действие имеет свой идентификаор (ID) и путь к его контроллеру. Действие также имеет вспомогательный URL для контекстно-зависимой помощи, когда контроллер активен и несколько других полей. Для действий, показанных в панели "Действия" слева, вы можете увидеть ID в скобках рядом с именем действия.

Добавление пункта меню в дерево для любого действия в панели управления выполняется, таким образом, путем создания пункта меню в правой панели и путем создания соответствующего действия (контроллера) или добавления обработчика. Если контроллер уже существует, вы можете просто выбрать его в выпадающем меню "Действия". Если нет, то вы должны создать действие в левой ппанели, которое указывает на контроллер. Например, нет пункта меню для создания нового пользователя, но поскольку для этого есть файл-контроллер, этот пункт может быть легко добавлен в верхнее меню. В этом случае нужно только создать пункт меню справа и для пространства имен "core" установить действие security/user/create. Как вы понимаете, пункт верхнего меню, который имеет обработчик, но не имеет соответствующего действия (подобно пункта меню "обновить сайт") в дереве "Действия". Ему не нужен пункт "Действие", поскольку обработчик содержит код для этого. Вместо запуска контроллера, MODX просто выполняет код в поле обработчика.

Обработка кликов в меню

Обратите внимание на действие index пространства имен Batcher в левой панели. Заметим его ID. Когда вы кликаете на пункте верхнего меню, MODX получает этот ID. Затем в панели управления генерируется URL этой страницы и пользователь попадает на нее. На нашем сайте этот ID равен 79. Когда мы кликаем на Batcher в верхнем меню, то видим в адресной строке браузера:

http://сайт/manager/index.php?a=79

Если вы кликаете на пункте меню Batcher, вы должны увидеть аналогичный URL, в котором вы увидите ID вашего index действия Batcher. Когда обработчик запросов получает этот URL, он проверяет наличие этого объекта меню в базе данных, наличие прав доступа у пользователя для его выполнения, устанавливает URL для помощи и выполняет файл-контроллер этого действия (если же имеется обработчик, то выполняется код JS обработчика).

Работа с верхним меню

Теперь, когда мы знаем как MODX обрабатывает элементы меню и связанные с ними действия, давайте модифицируем реальное верхнее меню в панели управления. Используемые методы достаточно просты и для их использования от вас не требуется понимания внутренних механизмов работы системы MODX меню/действие.

Будьте здесь осторожны, поскольку все ваши изменения будут по-прежнему в силе и при обновлении сайта и нет простого способа вернуться к меню по умолчанию. Большинство действий, которые мы будем предпринимать здесь, легко обратимы, но вам лучше записать первоначальную структуру меню до внесения изменений. Лучше вначале потренироваться на установке MODX, которая не будет использована для настоящего сайта.

Изменение порядка следования пунктов меню

Вы можете изменить порядок следования пунктов верхнего меню в панели управления или любых пунктов в их подменю. Перейдите в раздел Система->Действия и раскройте дерево меню справа (под заголовком "Верхнее меню").

Как мы выяснили ранее, это дерево является основой верхнего меню панели управления. Вы можете изменить порядок следования пунктов верхнего меню путем их перетаскивания. Просто нажмите элемент меню, который вы хотите переместить и, удерживая кнопку мыши нажатой, переместите туда, куда нужно и отпустите кнопку мыши. Таким образом вы можете изменить порядок пунктов верхнего меню или любого подменю. Вы можете переместить пункты из одного подменю в другое. Вы также можете переместить пункты подменю в верхнее меню путем перетаскивания их в папку верхнего меню. Для того, чтобы увидеть изменения, нужно перезагрузить страницу панели управления.

Добавление и удаление пунктов меню

Добавить новый пункт меню достаточно просто. Перейдите в раздел Система->Действия и раскройте дерево меню справа (под заголовком "Верхнее меню"). Выберите часть меню, к которому вы хотите добавить пункт и кликните на кнопке "Добавить меню" (или же кликнуть правой кнопкой и выбрать "Добавить пункт меню"). Введите имя нужного вам пункта меню и кликните кнопку "Сохранить". Обычно пользователи MODX вводят новые пункты в меню "Компоненты", но вы можете добавлять их где угодно. Для удаления пункта меню вы можете кликнуть правой кнопкой на нем и выбрать "Удалить пункт меню".

Если вы добавляете новый пункт меню и затем перегружаете страницу в браузере, вы можете и не увидеть ваш новый пункт в верхнем меню. Пункты верхнего меню без дочерних элементов и без указания действия или обработчика не будут отображаться в меню. Вот почему меню "Компоненты", которое вы видите в дереве, не отображается в меню, когда вы вначале установите MODX Revolution - пока не установлено никаких компонент.

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

Перейдите к разделу Система->Действия и (в дереве верхнего меню) кликните кнопку "Добавить меню". Введите в поле "Имя" название "Мое меню" и кликните на кнопке "Сохранить".

Имя - Новый документ

Действие - core-resource/create

Имя - Настройки системы

Действие - core-system/settings

Имя - Контроль доступа

Действие - core-security/permission

Убедитесь, что ваши три новые пункта меню являются подпунктами в меню "Мое меню". Если это не так, перетащите ихв нужное место мышью. Вы также можете изменить порядок следования меню и подменю.

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

Если вы хотите удалить любой пункт меню, который вы создали, просто перейдите к разделу Система->Действия , кликните на них правой кнопкой и выберите "Удалить". Хорошей идеей будет удаление всех подменю до удаления пункта главного меню, чтобы они не остались в базе данных.

Как спрятать пункты меню

Кроме изменения порядка следования пунктов меню вы также можете спрятать их, используя права доступа, прикрепленные к пункту меню. Перейдите к разделу Система->Действия и разверните дерево меню с правой стороны (под заголовком "Верхнее меню").

Кликните правой кнопкой на любом пункте или подпункте меню и выберите "Редактировать". Появится диалоговое окно с нижним полем "Права доступа". Будьте осторожны, чтобы не изменить никакого другого поля.

Если вы пытаетесь спрятать существующие пункты меню, вы увидите, что поле "Права доступа" у некоторых из них заполнено, а у некоторых нет. Какие действия необходимо предпринять, чтобы спрятать поле, зависит от того, заполнено ли это поле, или нет.

Если в поле "Права доступа" содержится список прав доступа, вы можете создать новую политику доступа (или отредактировать существующую) для блокировки этого права доступа и пункт меню будет спрятан. Эта операция может иметь побочные действия, поскольку другие пункты меню в панели управления могут зависеть от тех же прав доступа. Лучшим методом может быть добавление в это поле дополнительных спецификаций пользовательских прав доступа.

Поле "Права доступа" может содержать список прав доступа, разделенных запятыми. Данный пункт меню увидят только пользователи, имеющие все перечисленные права доступа.

Давайте посмотрим на пример. Предположим, что вам нужно спрятать от всех пользователей, за исключением пользователя с неограниченными правами Super User подменю "Управление пользователями" в меню "Безопасность".

Перейдите к разделу Система->Действия и раскройте дерево меню, а затем кликните правой кнопкой на подпункте "Управление пользователями" и выберите пункт "Редактировать". Поле "Права доступа" должно содержать view_user. Мы собираемся добавить другие права доступа под названием my_view_user_menu. Для этого отредактируйте это поле, чтобы оно содержало view_user,my_view_user_menu. Убедитесь, что во введенных данных нет пробелов. Теперь пользователям для того, чтобы увидеть подпункт "Управление пользователями", нужно иметь оба этих права доступа, и, поскольку ни у кого нет второго права доступа (поскольку мы только что его придумали), никто не увидит этот подпункт.

Для пунктов меню, которые не имеют прав доступа, процедура аналогична. Вы просто добавляете новые пользовательские права доступа в пустое поле "Права доступа".

Отметим, что после того, как мы добавили наши пользовательские права доступа, пользователь с неограниченными правами Super User также не будет видеть подменю "Управление пользователями". Для того, чтобы это поправить, нужно дать ему эти права доступа. Если вы планируете выполнять эти операции на реальном сайте, перед созданием пользовательских прав доступа всегда вначале давайте администратору с неограниченными правами эти права доступа.

Поскольку стандартная группа Administrator в панели управления защищена, вам требуется создать новый шаблон политики доступа, содержащий пользовательские права доступа и новую политику доступа, основанную на них. Вы можете поместить все ваши пользовательские права доступа в этот шаблон политики доступа. В разделе Безопасность->Контроль доступа кликните на "Создать шаблон политики доступа". Для диалога используйте следующие параметры:

Имя : CustomPermissionTemplate

Группа шаблонов : Admin

Описание :

После этого кликните правой кнопкой мыши на кнопке "Добавить разрешение". В диалоге используйте следующие параметры:

Имя : my_view_user_menu

Описание : Права доступа пользовательского меню

Затем кликните на закладке "Политика доступа", далее на кнопке "Создать политику доступа". В диалоге используйте следующие параметры:

Имя : CustomPermissions

Шаблон политики доступа : CustomPermissionTemplate

Описание : Мои пользовательские права доступа

Кликните на политике доступа "Custom permissions" и выберите "Редактировать". Прокрутите список вниз до права доступа my_view_user_menu и поставьте отметку в чекбоксе рядом. Кликните на кнопке "Сохранить" справа вверху.

Теперь нам нужно дать пользователю с неограниченными правами Super User это право доступа путем создания нового элемента списка управления доступом. Перейдите в раздел Безопасность->Контроль доступа->Группы пользователя ". Кликните правой кнопкой на пользовательской группе "Administrator" и выберите "Редактировать группу пользователей", кликните на закладке "Контекстный доступ" и затем на кнопке "Добавить контекст". Для диалога используйте следующие параметры:

Контекст : mgr

Минимальная роль : Super User - 0

Политика доступа : CustomPermissions

В верхнем меню выберите Безопасность->Контроль доступа . Никто не сможет увидеть этот пункт меню за исключением пользователя с неограниченными правами Super User (и еще пользователей с этой политикой доступа). Если вы зайдете в панель управления как один из редакторов сайта, подпункт "Управление пользователями" должен отсутствовать.

Назад Вперёд

Но ведь это не для нас;).

Мы же сделаем все с нуля. Зачем нам (мне) это понадобилось, ведь есть уже готовые варианты? Потому что мне так больше нравится. Потому что я считаю подобный подход наиболее верным. Потому что, умея разрабатывать свое, мы без труда сможем разобраться в чужом коде, изменить, исправить ошибки или дополнить его необходимым в конкретном случае функционалом. Да и, в конце концов, сделать свое - это зачастую так приятно!

Дальнейшее повествование будет подразумевать, что читатель обладает минимальным знанием PHP программирования. Теоретически те люди, которые совсем не понимают код, смогут скопировать код и воспроизвести все те действия, о которых пойдет речь ниже. Однако, возможно, для них будет лучше использовать готовые сниппеты а-ля Ditto, поскольку они предоставляют кучу возможностей для внешнего конфигурирования, не влезая в основной код.

Я не хочу дискутировать на тему, что лучше для пользователя - брать готовое или разрабатывать свое... И в том, и в другом случае есть свои плюсы и минусы. Лично для меня плюсов во втором варианте больше. Также и каждый из читателей определится сам.

Итак, взглянем вновь на наш . Поскольку разных программных частей в нашем сайте довольно много, а начинать с чего-то нужно, поэтому запрограммируем…

Верхнее меню

Под термином "верхнее меню" я понимаю набор ссылок на страницы в верхней части сайта (см. рисунок ниже):

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

Сравним с нашим деревом сайта в системе управления, которое мы построили в предыдущей статье:

Как видно из рисунка, в дереве сайта выделяются четыре документа (а именно "Блог", "Об авторах", "Фотографии" и "Обратная связь"), которые и создадут впоследствии ссылки в верхнем меню.

Также напомню, мы заранее скрыли документы, которые не хотим показывать в меню. Например, в настройках документа с названием "Поиск по сайту" убрали флажок "Показывать в меню", а оставшиеся два документа "Ссылки" и "Категории" мы скрыли на сайте, убрав флажок в настройках документа "Публиковать" (закладка "Настройки страницы" в настройках документа).

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

Перейдем теперь к вопросу отображения наших действий непосредственно на сайте.

Большую часть программ на сайте выполняют т.н. " ", т.е. отдельные куски кода (их также можно понимать как отдельные функции или подпрограммы) на PHP. Поэтому, чтобы реализовать в MODx вывод верхнего меню, мы также должны создать новый сниппет, запрограммировать его и добавить вызов этого сниппета в шаблоне в нужном месте.

Зайдем в систему управления, откроем закладку "Ресурсы" -> "Управление ресурсами" -> закладка "Сниппеты" и нажмем на ссылку "Новый сниппет". В поле "Название сниппета" впишем "TopMenu" без кавычек и пока просто сохраним пустой сниппет без кода. После сохранения мы увидим название нашего сниппета на закладке "Сниппеты".

Напомню, что в нашем шаблоне верхнее меню мы вынесли в чанк "TOPMENU". Переключимся на закладку "Чанки" и откроем чанк " ". В содержимом этого чанка мы увидим следующий код:


  • Блог

  • Об авторах

  • Фотографии

  • Обратная связь

Этот код как раз и создает наше меню. Закомментируем его и добавим вызов сниппета "TopMenu" в чанке:


[]

Здесь снова придется немного отвлечься, чтобы пояснить смысл этой конструкции []. Дело в том, что именно с помощью конструкций вида [] или [!SnippetName!] мы можем делать вызовы сниппетов в любом месте своих шаблонов, чанков и даже просто на любой отдельной странице сайта.

При этом конструкция [] обозначает вызов кэшируемого сниппета, т.е. вызов динамической подпрограммы, результат выполнения которой будет подсчитан и выполнен один раз, а впоследствии при загрузке страницы, где вызывается данный сниппет, результат будет неизменным, т.к. повторный вызов сниппета уже не происходит. Таким образом, мы экономим ресурсы своего веб-сервера (а это всегда имеет очень важное значение при высокой посещаемости ресурса).

Однако существуют ситуации, когда необходимо все время выполнять код сниппета заново и кэшировать результаты нельзя. В таких случаях используется конструкция [!SnippetName!], которая всегда заставит сниппет выполняться без кэширования. По аналогии, данная конструкция называется вызовом некэшируемого сниппета.

Итак, сохраним чанк "TOPMENU" и обновим страницу сайта. Хм, как ни странно, но верхнее меню исчезло. Но так ли это удивительно на самом деле? Закомментировав HTML код меню в чанке, мы скрыли его отображение в браузере (проверьте это, взглянув в исходный код HTML страницы). А наш сниппет "TopMenu" ничего не делает, поскольку в него еще ничего не добавлено. Исправим же этот недостаток:).

Перейдем снова на закладку "Сниппеты", откроем созданный сниппет "TopMenu" и попробуем протестировать его возможности… Терпение, мои продвинутые читатели, не всем знакомы эти детали.

Для начала напишем простейший код (обычный PHP код):

echo "Testing…";
?>

Перед сохранением выберем "Продолжить редактирование", т.к. нам придется еще не раз изменить содержимое нашего сниппета, и после этого сохраним сниппет. Обновим страницу сайта и увидим на месте верхнего меню… ну, по правде говоря, на первый взгляд мы не увидим почти никаких изменений, кроме слегка расширившегося синего фона меню. Нажмем "CRTL+A", чтобы выделить весь текст на странице сайта, и увидим, что все-таки наш сниппет вывел на месте меню текст "Testing…", просто цвет текста совпадает с цветом фона.

Изменим код сниппета на следующий:

echo "Testing...";
?>

Теперь мы ясно видим, что сниппет наш работает и даже (!) выводит некоторый текст. Что-ж, это прекрасно, но маловато для нашей задачи, поскольку мы должны добиться, чтобы наш сниппет выводил ссылки из системы управления, причем в точно таком же HTML коде, который мы закомментировали в чанке "TOPMENU".

И снова небольшое отвлечение...

Вся система взаимосвязей документов в MODx построена по принципу: каждый "родительский документ" содержит от нуля до множества "дочерних документов" ("parent" -> "childs").

Каждый документ в базе данных MODx имеет свой уникальный идентификатор "ID" - это то число, которое мы видим в скобках в дереве сайта рядом с каждым из документов.

Кстати говоря, этот уникальный идентификатор несет лишь одно единственное значение - он однозначно определяет конкретный документ в системе управления и ничего более ! Специально делаю акцент на этом факте, поскольку встречал неоднократные попытки изменить эти идентификаторы в самых разнообразных целях... Запомнить нужно сразу, что это просто бессмысленно, поэтому не пытайтесь менять эти цифры. На них вообще не стоит обращать много внимания, обычно эти цифры используются просто для генерации ссылок на определенные документы.

В базе данных MODx для каждого документа также создано специальное поле "parent". Значением данного поля является число, обозначающее либо уникальный идентификатор родительского документа, либо, если документ находится в корне дерева, нуль. Таким образом, всегда можно однозначно определить, какой именно документ является для данного родительским.

Чтобы наглядно увидеть то, о чем мы сейчас говорили, откройте phpMyAdmin, выберите свою базу данных и найдите таблицу {PREFIX}site_content, где {PREFIX} - Ваш префикс, который Вы ввели при установке. Вы увидите множество полей, в которых сохраняются определенные данные документов, в том числе "ID" - уникальный идентификатор, "parent" - номер родительского документа, "pagetitle" - заголовок страницы и другие.

Итак, используя данную информацию о принципе хранения и связи документов в MODx, мы можем понять, как получить нужные данные для вывода ссылок верхнего меню: нам нужно найти в базе данных все документы, которые находятся в корне дерева сайта, т.е. имеют в поле "parent" значение нуль.

Используя SQL язык, подобный запрос описывается как-то так (Вы можете попробовать ввести данный запрос в поле ввода SQL в phpMyAdmin, предварительно заменив "modx_" на свой префикс):

SELECT *
FROM `modx_site_content`
WHERE `parent` = 0;

Однако такой запрос возвратит нам абсолютно все документы из корня сайта, что не совсем правильно, исходя из основной задачи - вывести ссылки только на те документы, которые имеют:

  • опубликованный статус (в БД за этот пункт отвечает поле "published", где значение = 1 обозначает, что документ опубликован, а значение = 0 - неопубликован).
  • неудаленные (поле "deleted", где 1 - удален, а 0 - не удален),
  • и у которых установлена опция "Показывать в меню" (поле "hidemenu", где 1 - скрывать, а 0 - показывать в меню).

Кроме того, забегая немного вперед, мы сразу отсортируем документы по параметру "Позиция в меню", который будет определять позицию каждой ссылки в нашем меню.

Ну, с точки зрения SQL, это совсем несложная задача и решается она так:

SELECT *
FROM `modx_site_content`
WHERE `published` = 1
AND `parent` = 0
AND `deleted` = 0
AND `hidemenu` = 0
ORDER BY `menuindex` ASC;

Теоретически все SQL запросы можно выполнять в сниппетах напрямую с помощью PHP скриптов, подключая каждый раз базу данных заново и делая множество других рутинных операций, повторяя их раз за разом… Но, согласитесь, это нивелировало бы смысл использования фреймворка, коим безусловно является наша система управления, т.к. MODx, помимо прочих своих достоинств, предоставляет готовый набор средств программного интерфейса (API, Application Programming Interface). API - это программные функции, которые унифицируют и облегчают многие процессы обработки данных.

Используем одну из упомянутых функций API "getDocumentChildren " в нашем сниппете. Функция "getDocumentChildren" получает в виде параметров следующие данные:

  • $id - номер родительского документа,
  • $active - выбирать только опубликованные или неопубликованные документы (1 или 0 соответственно),
  • $deleted - выбирать только удаленные или неудаленные документы (1 | 0),
  • $fields - поля, которые выбираются из БД,
  • $where - специальные условия, т.е. условие WHERE в SQL запросе,
  • $sort - поле, по которому должна проводиться сортировка результатов
  • $direction - направление сортировки, может принимать значения ASC или DESC, т.е. сортировка от меньшего к большему значению или наоборот
  • $limit - ограничение запроса, т.е. условие LIMIT в SQL запросе

$results = $modx->getDocumentChildren(
$id = 0,
$active = 1,
$deleted = 0,
$where = "hidemenu = 0",
$sort="menuindex",
$dir="ASC",
$limit
);

Print("

Foreach($results as $key => $value) {
print_r($value);
}

Print("");
?>

Сохраните сниппет и обновите страницу. В результате выполнения обновленного сниппета "TopMenu" Вы увидите список из массивов и их значений, отсортированный по значениям поля "menuindex" от меньшего значения к большему. Попробуйте поменять параметр $dir="ASC" на $dir="DESC" - в результате массивы перестроятся и первым документом будет выведен документ с наибольшим значением поля "menuindex".

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

$results = $modx->getDocumentChildren(
$id = 0,
$active = 1,
$deleted = 0,
"id, pagetitle, published, menuindex, deleted, hidemenu, menutitle",
$where = "hidemenu = 0",
$sort="menuindex",
$dir="ASC",
$limit
);

$items = "";
$output = "";

Foreach($results as $key => $value) {
$items .= "


  • ".$value["pagetitle"]."
  • \n";
    }

    If ($items != "") {
    $output = "

      \n";
      $output .= $items;
      $output .= "
    \n";
    }

    Return $output;

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

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

    Т.е. это уже автоматически сгенерированные ссылки, структура которых полностью повторяет структуру документов в дереве MODx. Чтобы проверить это, попробуйте создать какой-нибудь тестовый документ в корне сайта и обновите страницу.

    Однако это еще не все. Многие уже наверняка заметили, что ссылки есть, но ссылок нет... Парадокс:). Я имею ввиду, что названия документов в меню выводятся, однако ссылки на них не работают. Это логично, поскольку пока в коде ссылок выводится "#" вместо реальных путей.

    Чтобы решить эту задачку, необходимо узнать еще об одной крайне полезной возможности MODx: адрес любой внутренней страницы сайта можно получить с помощью следующей конструкции [~id~], где id - это уникальный номер нужного документа, т.е. тот самый номер, указанный в скобках рядом с названием каждого документа в дереве сайта. Таким образом, добавив такую конструкцию [~1~] в шаблоне/чанке/содержимом страницы,

      • index – алиас документа "Блог", если мы ввели "index" как алиас документа, либо
      • 1.html, если мы не вводили ничего в поле "Псевдоним" для документа "Блог"
    • если дружественные ссылки отключены, то увидим текст index.php?id=1

    Перепишем сниппет, используя эту информацию:

    $results = $modx->getDocumentChildren(
    $id = 0,
    $active = 1,
    $deleted = 0,
    "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle",
    $where = "hidemenu = 0",
    $sort="menuindex",
    $dir="ASC",
    $limit
    );

    $items = "";
    $output = "";

    Foreach($results as $key => $value) {
    $items .= "


  • ".$value["pagetitle"]."
  • \n";
    }

    If ($items != "") {
    $output = "

      \n";
      $output .= $items;
      $output .= "
    \n";
    }

    Return $output;

    Таким образом, мы изменили # на [~".$value["id"]."~], т.е. фактически для каждого документа из массива подставляется его уникальный ID внутри конструкции [~id~]. В результате мы получаем меню с работающими ссылками.

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

    Чтобы добиться этого, мы снова приоткроем секреты MODx CMS:). В API скрыта функция $modx->documentIdentifier , которая возвращает значение уникального идентификатора текущей страницы. Она нам понадобится для определения активной страницы и выделения ее в меню:

    $results = $modx-> getDocumentChildren (
    $id = 0,
    $active = 1,
    $deleted = 0,
    "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle",
    $where = "hidemenu = 0",
    $sort="menuindex",
    $dir="ASC",
    $limit
    );

    $cid = $modx->documentIdentifier;

    $items = "";
    $output = "";

    Foreach($results as $key => $value) {
    if ($value["id"] == $cid) {
    $active = " id=\"active\"";
    }
    else {
    $active = "";
    }
    $items .= "
    ".$value["pagetitle"]."
    \n";
    }

    If ($items != "") {
    $output = "

      \n";
      $output .= $items;
      $output .= "
    \n";
    }

    Return $output;

    Ну как, получилось? Получилось!

    Но Вы же не подумали, что на этом все и закончится? И правильно. Мы ставим себе самую высокую планку, мы хотим задействовать максимум возможностей MODx. А поэтому еще одна небольшая деталь, которую мы упустили.

    Посмотрим внимательно на название полей, которые мы запрашиваем с помощью функции getDocumentChildren: "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle". Среди них есть такое поле, как "menutitle". Как следует из названия, в данном поле может храниться заголовок меню . В системе управления также имеется поле ввода "Пункт меню". Это поле заполнять необязательно. Однако логика в том, что если это поле заполнено, то мы должны заменить текст ссылки в меню на введенный пользователем. Ну, так сделаем это:

    /********************************
    Название: TopMenu
    Цель: Вывод верхнего меню
    Проект: Демосайт MODx
    ********************************/

    $results = $modx->getDocumentChildren(
    $id = 0, // ID родительского документа
    $active = 1, // Выбираем только опубликованные документы
    $deleted = 0, // Выбираем только неудаленные документы
    "id, pagetitle, published, menuindex, deleted, hidemenu, menutitle", // Выбираем поля из БД
    $where = "hidemenu = 0", // Выбираем только те документы, которые нужно публиковать в меню
    $sort="menuindex", // Сортируем документы по полю menuindex
    $dir="ASC", // Сортируем документы по возрастанию
    $limit = "" // Ограничения не устанавливаем (параметр LIMIT в SQL запросе)
    );

    $cid = $modx->documentIdentifier; //получаем ID текущей страницы

    $items = "";
    $output = "";

    Foreach($results as $key => $value) {
    if ($value["id"] == $cid) {
    $active = " id=\"active\"";
    }
    else {
    $active = "";
    }
    if ($value["menutitle"] != "") {
    $title = $value["menutitle"];
    }
    else {
    $title = $value["pagetitle"];
    }
    $items .= "
    ".$title."
    \n"; //собираем пункты меню
    }

    // Если удалось найти хотя бы один пункт меню,
    // создаем HTML код меню
    if ($items != "") {
    $output = "

      \n";
      $output .= $items;
      $output .= "
    \n";
    }

    // Возвращаем результат работы сниппета
    return $output;

    Попробуйте теперь ввести какой-нибудь текст в поле ввода "Пункт меню" любого документа... Все работает? Замечательно!

    P.S.: Возможно, некоторые читатели будут удивлены, что при переходе по ссылкам нашего меню содержимое страниц не изменяется, хотя вроде бы, судя по пути в адресе браузера, мы переходим на новые страницы… Поверьте, это абсолютно нормально, т.к. абсолютно все страницы на текущий момент используют один и тот же шаблон. В этом шаблоне фактически мы пока сделали динамическим только верхнее меню, все остальные детали остаются неизменными. Мы обязательно займемся этим позже, а пока - без паники;).

    Заключение:

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

    Итоги обучения:

    • Мы попробовали разобраться в назначении некоторых полей ввода документов MODx и рассмотрели хранение этой информации в базе данных;
    • Узнали о новых специальных конструкциях MODx: [], [!SnippetName!], [~id~];
    • Узнали о наличии специального API и воспользовались некоторыми функциями API;
    • И на основе этих знаний создали свой новый сниппет в MODx!

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

    Создавать динамическое меню в MODX мы будем при помощи сниппета PdoMenu из пакета pdoTools . Перед тем как начать ознакомьтесь с основной документацией.

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

    Параметры

    Параметры шаблонов

    Параметры CSS классов

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


    официальную документацию можете почитать здесь . А сейчас разберем самые типовые вызовы меню.

    Вызов PdoMenu

    Вариант 1 . На месте этого статического меню вызовем сниппет pdoMenu , для этого в дереве ресурсов, на вкладке “Элементы ” в разделе сниппеты разверните ветку pdoTools , далее нажмите на pdoMenu левой кнопкой мыши (не отпускайте кнопку) и перетащите этот сниппет в место, где вы хотите вызвать меню, далее в открывшемся окошке заполните необходимые параметры и нажмите «Сохранить «.

    Вариант 2 . Просто вручную пишем вызов.

    Типовые примеры

    Обычное одноуровневое меню

    К примеру у нас самое обычное меню, со следующей html разметкой.

    Получился вот такой код с вызовом меню:

    • &parents=`0` — список родителей (в моем случае я не ограничиваю выборку, так как я все равно выведу только определенные страницы);
    • &level=`1` — уровень вложенности (в данном случае ее нет);
    • &resources=`2,3,4,5` — список ресурсов которые нужно вывести в меню;
    • &firstClass=`0` — класс для первого пункта меню (не какого);
    • &lastClass=`0` — класс последнего пункта меню (не какого);
    • &outerClass=`top-menu` — класс обертки меню (подставляется в ul);
    • &hereClass=`current-menu-item` — класс для активного пункта меню (подставляется в li);
    • &rowClass=`menu-item` — класс одной строки меню (подставляется в li).

    Двухуровневое кастомное bootstrap меню

    Статический html код выглядит так:

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

    Так же в следующем уроке я приведу еще пару выводов выпадающих меню, на основе bootstrap ( и , это для тех кто не уловил суть. Ну а далее сделаем .

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