При работе с проектами на MODX Revolution нередко возникает ситуация, когда в ресурсе нужно повторно использовать данные, уже заданные в родительской категории. Чаще всего это касается дополнительных полей (TV) с типом MIGX: т.е. мы выводим значения заполненные в одном ресурсе на других, с этим проблем нет и как это делать я уже рассказывал, вот например: Вывод TV поля MIGX одного ресурса на другом.
Например, конкретно данном случае при помощи Fenom можно вывести значения TV родителя можно так:
{set $rows = json_decode($_modx->resource.parent | resource : "name_tv", true)}
{foreach $rows as $row}
и здесь весь код блока размеченный полями примерно вот так: {$row.title} {$row.znachenie} ...
{/foreach}
Но бывают ситуации, когда один и тот же набор параметров нужно унаследовать, а затем — при необходимости — изменить. Вот здесь уже стандартного функционала недостаточно (ну или не совсем достаточно) и сейчас я с вами поделюсь, как решить такую задачу.
Постановка задачи
Ко мне обратились с задачей: расширить блок «Информация о товаре». Он сейчас заполняется в TV baseproduct (MIGX) на уровне категории. Нужно было добавить возможность дополнять/изменять отдельные значения на уровне карточки товара.
📄 Полный текст ТЗ: посмотреть / скачать PDF
Условия задачи
У нас есть TV baseproduct с конфигурацией MIGX, назначенный на родительские ресурсы (категории).
Пример конфигурации (фрагмент JSON):
{
"formtabs":[
{
"fields":[
{
"field":"title",
"caption":"Название"
},
{
"field":"znachenie",
"caption":"Значение"
}
]
}
],
"columns":[
{
"header":"Название",
"dataIndex":"title"
},
{
"header":"Значение",
"dataIndex":"znachenie"
}
]
}
Категории уже заполнены — у каждой есть свои параметры.
Теперь мы создаём ещё одно TV (например, productparams) с типом MIGX с точно такой же конфигурацией полей и назначаем его для шаблона дочерних ресурсов.
Далее у нас есть 2 пути.
Решение «в лоб» (не совсем то, но похоже)
Первое, что приходит в голову: проверять TV на пустоту и подставлять либо свои значения, либо родительские.
Пример на Fenom:
{if $_modx->resource.productparams?}
{set $rows = json_decode($_modx->resource.productparams, true)}
<div class="r_card__row">
<div class="r_card__about-title">{$row.title}</div>
<div class="r_card__about-value">{$row.znachenie}</div>
</div>
{/foreach}
{else}
{set $rows = json_decode($_modx->resource.parent | resource : "baseproduct", true)}
<div class="r_card__row">
<div class="r_card__about-title">{$row.title}</div>
<div class="r_card__about-value">{$row.znachenie}</div>
</div>
{/foreach}
{/if}
Что мы получаем:
- Если у ресурса заполнено
productparams→ выводим его. - Если пусто → подставляем данные из
baseproductродителя.
Кому-то этого достаточно. Но по факту это неудобно: если нужно изменить всего одно значение, придётся переписать весь массив заново.
Решение с PHP и @EVAL
Правильнее подставлять значения родителя сразу в TV при редактировании ресурса. Тогда редактор увидит готовый список и изменит только нужное.
Для этого используем @EVAL.
В MODX у TV есть полезная возможность — использовать префиксы для значений. Обычно мы встречаем такие как @INLINE, @FILE, @CHUNK, @RESOURCE и др. Они говорят MODX, откуда брать данные для TV.
@EVAL — один из таких префиксов, и он самый «гибкий». Его задача простая: выполнить PHP-код и вернуть результат. То есть всё, что вы напишете в @EVAL …, будет обработано PHP, а результат выполнения подставлен в TV.
Простейший пример:
@EVAL return date("Y-m-d");
Такое TV всегда будет содержать текущую дату.
Или чуть сложнее:
@EVAL return $modx->resource->get('pagetitle');
Здесь в TV автоматически подставится заголовок текущей страницы.
По сути, @EVAL превращает TV в «мини-скрипт», который каждый раз возвращает актуальное значение. Именно поэтому мы можем использовать его для динамического наследования данных из родителя: PHP-код берёт MIGX родителя, обрабатывает и подставляет готовый массив в дочерний ресурс.
⚠️ Важно: @EVAL — мощный, но опасный инструмент. Любая ошибка в коде может поломать вывод TV, а при неправильной работе — даже замедлить сайт. Поэтому:
- всегда пишите аккуратный, проверенный код;
- используйте только там, где реально нужна динамика.
В TV productparams, во вкладке Параметры ввода, в поле значение по умолчанию

прописываем следующее:
@EVAL
global $modx;
$parentId = $modx->controller->resource->parent;
if (!$parentId) return '[]';
$category = $modx->getObject('modResource', $parentId);
if (!$category) return '[]';
$baseproductTV = $category->getTVValue('baseproduct');
if (empty($baseproductTV)) return '[]';
$data = $modx->fromJSON($baseproductTV);
$result = [];
if (is_array($data)) {
foreach ($data as $item) {
if (is_array($item) && !empty($item['title'])) {
$value = '';
if (!empty($item['znachenie'])) {
$value = $item['znachenie'];
} elseif (!empty($item['value'])) {
$value = $item['value'];
} elseif (!empty($item['default'])) {
$value = $item['default'];
}
$result[] = [
'title' => $item['title'],
'znachenie' => $value
];
}
}
}
return $modx->toJSON($result);
Ну и выводим это TV. Теперь в него автоматически подставляется массив с параметрами родителя. И при необходимости редактор может изменить отдельные значения — без копирования всего списка вручную.
Расширенный вариант
Более универсальное решение — с обработкой разных сценариев и определением parentId даже при создании ресурса:
@EVAL
global $modx;
$parentId = 0;
if (!empty($modx->controller) && !empty($modx->controller->resource)) {
$parentId = (int)$modx->controller->resource->get('parent');
} elseif (!empty($modx->resource) && $modx->resource instanceof modResource) {
$parentId = (int)$modx->resource->get('parent');
} elseif (!empty($_REQUEST['parent'])) {
$parentId = (int)$_REQUEST['parent'];
}
if (!$parentId) return '[]';
$category = $modx->getObject('modResource', $parentId);
if (!$category) return '[]';
$baseproductTV = $category->getTVValue('baseproduct');
if (empty($baseproductTV)) return '[]';
$data = $modx->fromJSON($baseproductTV);
$result = [];
if (is_array($data)) {
foreach ($data as $item) {
if (is_string($item)) {
$title = $item;
$item = ['title' => $title];
} elseif (is_array($item) && !empty($item['title'])) {
$title = $item['title'];
} else {
continue;
}
$value = '';
if (!empty($item['znachenie'])) {
$value = $item['znachenie'];
} elseif (!empty($item['value'])) {
$value = $item['value'];
} elseif (!empty($item['default'])) {
$value = $item['default'];
}
$result[] = [
'title' => $title,
'znachenie' => $value,
'value' => $value
];
}
}
return $modx->toJSON($result);
Итог
Мы решили задачу так:
- Родительская категория хранит полный набор параметров в MIGX.
- При создании/редактировании дочернего ресурса TV автоматически заполняется значениями родителя.
- Редактор меняет только то, что нужно.
✅ Экономия времени
✅ Минимум ошибок
✅ Гибкость
Такой подход подойдёт не только для характеристик товаров, но и для любых параметров, которые повторяются у дочерних ресурсов (метатеги, реквизиты, описания блоков и т.д.).
Заключение
Как видите, даже такие нетривиальные задачи в MODX, как наследование и автозаполнение MIGX TV, решаются довольно изящно — нужно лишь немного «поиграть» с Fenom и @EVAL. Это экономит время редакторам, снижает риск ошибок и делает работу с проектом более удобной.
Если у вас есть похожие задачи или вы хотите доработать сайт на MODX — пишите, помогу найти решение под ваш проект.
📩 Контакты для связи: [Telegram — @alex87ru]









