- Зачем это нужно?
- Основные подходы
- 1. Использование плейсхолдера
- 2. Применение компонента fastField
- Практический пример.
- 3. Использование сниппета pdoField
- 4. Использование метода getParentIds класса modX
- 5. Использование метода getObject класса modX
- 6. Использование $modx->resource
- Практический пример: вывод цепочки навигации
- Работа с TV-параметрами
- 7. Использование прочих сниппетов
- getResourceField
- UltimateParent
- getResource / pdoResource
- Заключение
Зачем это нужно?
Прежде чем углубляться в технические детали, давайте разберёмся, почему это может быть полезно. Представьте, что вы создаёте сайт, где каждая страница должна отображать заголовок своего раздела (родителя) или даже название сайта из корневого ресурса (прародителя). Или, например, вам нужно вывести изображение, заданное в родительском ресурсе, если оно не указано в текущем. Такие задачи встречаются довольно часто, и MODX предоставляет несколько способов их решения.
Основные подходы
В MODX Revolution есть несколько инструментов и методов, которые позволяют работать с иерархией ресурсов.
1. Использование плейсхолдера
Каждый ресурс в MODX содержит поле parent
, которое хранит идентификатор его непосредственного родителя. Для доступа к этому значению используется плейсхолдер: [[*parent]]
.
Этот подход позволяет получить ID родительского ресурса и использовать его в дальнейшем для извлечения других полей.
2. Применение компонента fastField
Компонент fastField
устанавливать не нужно (он устарел и скорее всего сломает ваш сайт). Функционал данного компонента давным давно включен в пакет pdoTools. Он предоставляет удобный синтаксис для быстрого доступа к полям ресурсов:
[[#[[*parent]].pagetitle]]
В данном примере извлекается значение поля pagetitle
родительского ресурса. Аналогично можно получить поля ресурсов на более высоких уровнях иерархии:
<!-- ID дедушки -->
[[#[[*parent:parent]].pagetitle]]
<!-- просто id -->
[[#34.pagetitle]]
<!-- id из GET параметра -->
[[#[[#GET.key]].pagetitle]]
Практический пример.
Допустим нам нужно сослаться в ресурсе на родителя и прародителя, сделать это можно вот так:
<a href="[[~[[#[[*parent]].id]]]]">[[#[[*parent]].pagetitle]]</a>
<a href="[[~[[#[[#[[*parent]].parent]].id]]]]">[[#[[#[[*parent]].parent]].pagetitle]]</a>
<a href="{($_modx->makeUrl($_modx->resource.parent))}">{$_modx->resource.parent | resource : 'pagetitle'}</a>
{($_modx->resource.parent | resource : 'parent') | resource : 'pagetitle'} )
{($_modx->resource.parent | resource : 'parent') ? '<a href="' ~ $_modx->makeUrl(($_modx->resource.parent | resource : 'parent')) ~ '">' ~ (($_modx->resource.parent | resource : 'parent') | resource : 'pagetitle') ~ '</a>' : ''}
или
{var $grandparentId = ($_modx->resource.parent | resource : 'parent')}
{if $grandparentId}<a href="{$_modx->makeUrl($grandparentId)}">{($grandparentId | resource : 'pagetitle')}</a>{/if}
3. Использование сниппета pdoField
Сниппет pdoField
, входящий в состав пакета pdoTools, является мощным инструментом для получения полей предковых ресурсов. Он обладает высокой производительностью и гибкостью.
Примеры использования:
<!-- Получение поля 'pagetitle' родительского ресурса -->
[[pdoField?
&top=`2`
&field=`pagetitle`
]]
<!-- Получение поля 'pagetitle' дедушкиного ресурса -->
[[pdoField?
&top=`3`
&field=`pagetitle`
]]
Параметр &top
указывает уровень предка, где 2
— родитель, 3
— дедушка и т.д. Параметр &field
определяет, какое именно поле необходимо получить. Кроме того pdoField
поддерживает использование в качестве фильтра вывода:
[[*id:pdoField=`pagetitle`]]
Также можно передавать параметры в формате JSON:
[[*id:pdoField=`{"top":2,"field":"pagetitle"}`]]
4. Использование метода getParentIds
класса modX
В сниппетах и плагинах можно использовать возможности xPDO для получения идентификаторов родительских ресурсов. Метод getParentIds
класса modX
позволяет получить массив идентификаторов всех предков ресурса до указанного уровня вложенности:
// Получение всех родительских идентификаторов для ресурса с ID 23
$parentIds = $modx->getParentIds(23, 10, array('context' => 'web'));
Важно учитывать, что этот метод использует контекстный кэш для получения родительских идентификаторов. Если не указать контекст в параметре options
, он будет использовать текущий контекст, который в плагине или внешнем приложении часто является "mgr"
. Поэтому рекомендуется явно указывать контекст, например 'web'
.
5. Использование метода getObject
класса modX
Если необходимо получить конкретные поля родительского ресурса, можно использовать метод getObject
:
// Получение объекта родительского ресурса
$parentResource = $modx->getObject('modResource', $modx->resource->get('parent'));
// Получение значения поля 'pagetitle' родительского ресурса
$parentPagetitle = $parentResource ? $parentResource->get('pagetitle') : '';
Для получения значения дополнительного поля (TV) родительского ресурса:
// Получение значения TV-параметра 'tvName' родительского ресурса
$tvValue = $parentResource ? $parentResource->getTVValue('tvName') : '';
6. Использование $modx->resource
Объект $modx->resource
представляет текущий ресурс и даёт доступ к его свойствам и методам. Чтобы получить данные родителя или прародителя, можно воспользоваться вышеуказанным методом getParentIds()
или напрямую запросить объект родителя через getOne()
.
Пример получения заголовка родителя:
$parent = $modx->resource->getOne('Parent');
if ($parent) {
$parentTitle = $parent->get('pagetitle');
echo $parentTitle;
}
Для прародителя нужно сделать ещё один шаг:
$parent = $modx->resource->getOne('Parent');
if ($parent) {
$grandparent = $parent->getOne('Parent');
if ($grandparent) {
$grandparentTitle = $grandparent->get('pagetitle');
echo $grandparentTitle;
}
}
Этот подход гибок, так как позволяет работать с любыми полями ресурса (включая TV-параметры) и не ограничивается только стандартными полями, такими как pagetitle
или content
.
Практический пример: вывод цепочки навигации
Допустим, вы хотите вывести на странице цепочку вида: «Главная → Раздел → Подраздел». Это можно сделать с помощью следующего кода:
// В сниппете или шаблоне
$current = $modx->resource->get('pagetitle');
$parent = $modx->resource->getOne('Parent');
$navigation = [$current];
if ($parent) {
$navigation[] = $parent->get('pagetitle');
$grandparent = $parent->getOne('Parent');
if ($grandparent) {
$navigation[] = $grandparent->get('pagetitle');
}
}
echo implode(' → ', array_reverse($navigation));
Результат: «Главная → Раздел → Подраздел».
Работа с TV-параметрами
Если вам нужно получить TV-параметр (например, bannerImage
) родителя или прародителя, это тоже возможно. Пример с $modx->resource
:
$parent = $modx->resource->getOne('Parent');
if ($parent) {
$banner = $parent->getTVValue('bannerImage');
if ($banner) {
echo '<img src="' . $banner . '" alt="Banner">';
}
}
7. Использование прочих сниппетов
getResourceField
Сниппет getResourceField
позволяет получить значение любого поля указанного ресурса. Пример использования:
[[getResourceField? &id=`[[*parent]]` &field=`pagetitle`]]
В этом примере мы получаем значение поля pagetitle
родительского ресурса текущего ресурса.
UltimateParent
Сниппет UltimateParent
позволяет получить данные о самом верхнем родительском ресурсе в иерархии. Пример использования:
[[UltimateParent? &field=`pagetitle`]]
Этот сниппет возвращает значение указанного поля для самого верхнего родительского ресурса текущего ресурса.
getResource / pdoResource
Для более сложных сценариев удобно применять сниппеты, такие как getResources
или pdoResources
(из пакета pdoTools). Эти инструменты позволяют извлекать данные из ресурсов по заданным условиям, включая иерархию.
Пример с pdoResources
для получения заголовка родителя:
[[pdoResources?
&parents=`0`
&resources=`[[*parent]]`
&tpl=`@INLINE [[+pagetitle]]`
&includeTVs=`1`
&tvPrefix=``
]]
А для прародителя можно сначала получить ID родителя, а затем запросить его родителя:
[[!pdoResources?
&parents=`0`
&resources=`[[*parent]]`
&tpl=`@INLINE [[!pdoResources? &parents=`0` &resources=`[[+parent]]` &tpl=`@INLINE [[+pagetitle]]`]]`
&includeTVs=`1`
&tvPrefix=``
]]
Этот подход особенно удобен, если вам нужно обработать сразу несколько ресурсов или вывести данные в сложном формате.
Заключение
MODX предоставляет множество инструментов для работы с данными родителей и прародителей ресурсов. Выбор метода зависит от конкретной задачи. Экспериментируйте с этими подходами, чтобы найти оптимальное решение для вашего проекта.