Сниппет getPageBlockContent для вывода блоков PageBlocks (Free версия) с других страниц в MODX

В бесплатной версии PageBlocks нет встроенного инструмента для вывода блоков с другой страницы. Этот сниппет решает задачу через xPDO-запрос к таблице pbBlockValue. Он позволяет выводить указанные блоки с любого ресурса, с опциями сортировки, лимита и обёртки.


Установка

Если работаете с файловыми элементами (PdoTools), создайте файловый сниппет getPageBlockContent.php в директории (../elements/snippets/). Либо создайте обычный сниппет getPageBlockContent в админке MODX со следующим кодом:
<?php
/**
 * getPageBlockContent v1.1
 * Вывод блоков PageBlocks с любой страницы (Free версия)
 * 
 * Параметры:
 * @param int    $resourceId   ID страницы-источника (обязательный)
 * @param string $blockIds     ID блоков через запятую (обязательный)
 * @param string $tpl          Чанк для рендера (опционально, по умолчанию из блока)
 * @param int    $limit        Лимит блоков (0 = все)
 * @param string $sortby       Сортировка (menuindex, id)
 * @param string $sortdir      Направление (ASC, DESC)
 * @param string $wrapper      Обёртка для всех блоков (@INLINE <div>{$output}</div>)
 * @param string $toPlaceholder Сохранить в placeholder вместо вывода
 * 
 * Примеры:
 * [[!getPageBlockContent? &resourceId=`10` &blockIds=`4,7,21`]]
 * {'!getPageBlockContent' | snippet : ['resourceId' => 10, 'blockIds' => '4,7']}
 */

// 1. Загрузка pdoTools для рендеринга чанков
if ($modx->services instanceof MODX\Revolution\Services\Container) {
    $pdotools = $modx->services->get('pdotools');
} else {
    $pdotools = $modx->getService('pdotools', 'pdoTools', 
        MODX_CORE_PATH . 'components/pdotools/model/', $scriptProperties);
}

if (!$pdotools) {
    $pdotools = $modx;
}

// 2. Загрузка модели PageBlocks
$corePath = $modx->getOption('pageblocks_core_path', null, 
    $modx->getOption('core_path') . 'components/pageblocks/');
$modx->addPackage('pageblocks', $corePath . 'model/');

// 3. Получение параметров
$resourceId = (int)$modx->getOption('resourceId', $scriptProperties, 0);
$blockIds = $modx->getOption('blockIds', $scriptProperties, '');
$tpl = $modx->getOption('tpl', $scriptProperties, '');
$limit = (int)$modx->getOption('limit', $scriptProperties, 0);
$sortby = $modx->getOption('sortby', $scriptProperties, 'menuindex');
$sortdir = strtoupper($modx->getOption('sortdir', $scriptProperties, 'ASC'));
$wrapper = $modx->getOption('wrapper', $scriptProperties, '');
$toPlaceholder = $modx->getOption('toPlaceholder', $scriptProperties, '');

// Проверка обязательных параметров
if (empty($resourceId) || empty($blockIds)) {
    return '';
}

// 4. Парсинг ID блоков
$ids = array_map('trim', explode(',', $blockIds));
$ids = array_filter($ids, 'is_numeric');

if (empty($ids)) {
    return '';
}

// 5. Формирование xPDO запроса
$c = $modx->newQuery('pbBlockValue');
$c->where([
    'model_id' => $resourceId,
    'id:IN' => $ids,
    'published' => 1,
    'deleted' => 0
]);

$c->sortby($sortby, $sortdir);

if ($limit > 0) {
    $c->limit($limit);
}

// 6. Получение блоков
$items = $modx->getIterator('pbBlockValue', $c);

$list = [];
$idx = 0;

foreach ($items as $item) {
    // Декодируем JSON значения и объединяем с полями объекта
    $values = array_merge(
        json_decode($item->get('values'), true) ?: [], 
        $item->toArray()
    );
    
    $values['resource_id'] = $item->get('model_id');
    $values['id'] = $item->get('id');
    $values['idx'] = $idx;
    $values['pls'] = $values;
    
    // Выбор чанка для рендеринга
    $chunkName = $tpl ?: $item->get('chunk');
    
    // Рендеринг блока
    $list[] = $pdotools->getChunk($chunkName, $values);
    $idx++;
}

// 7. Формирование вывода
$output = implode("\n", $list);

// Обёртка
if (!empty($wrapper)) {
    $output = str_replace('{$output}', $output, $wrapper);
}

// Вывод или placeholder
if (!empty($toPlaceholder)) {
    $modx->setPlaceholder($toPlaceholder, $output);
    return '';
}

return $output;
Параметры сниппета


Примеры использования
Для тех кто использует файлы:
Прямой вызов @FILE:
{'@FILE snippets/getPageBlockContent.php' | snippet : [
    'resourceId' => 10,
    'blockIds' => '4,7,11'
]}
Через runSnippet:
{$_modx->runSnippet('@FILE snippets/getPageBlockContent.php', [
    'resourceId' => 10,
    'blockIds' => '4,7,11'
])}
Для тех кто использует обычный сниппет:
Базовый вывод (Fenom):
{'!getPageBlockContent' | snippet : [
    'resourceId' => 10,
    'blockIds' => '4,7,21'
]}
С лимитом и сортировкой:
{'!getPageBlockContent' | snippet : [
    'resourceId' => 20,
    'blockIds' => '10,11,12,13,14',
    'limit' => 3,
    'sortdir' => 'DESC'
]}
С кастомным чанком:
[[!getPageBlockContent? 
    &resourceId=`15` 
    &blockIds=`1,2,3,4,5`
    &tpl=`reviews_card`
]]
С обёрткой:
[[!getPageBlockContent?
    &resourceId=`25`
    &blockIds=`5,6,7`
    &wrapper=`@INLINE <div class="carousel-inner">{$output}</div>`
]]
В placeholder:
{'!getPageBlockContent' | snippet : [
    'resourceId' => 30,
    'blockIds' => '8,9',
    'toPlaceholder' => 'testimonials_html'
]}

<section class="testimonials">
    {$testimonials_html}
</section>
Этот сниппет совместим с MODX 3 и PageBlocks Free. Для более сложных задач рассмотрите PRO-версию PageBlocks.

Важно! Работает только с опубликованными блоками.

Нашли баги, welcome на github.

На базе этого сниппета так же можно создать «Универсальный блок» в админке PageBlocks, чтобы контент-менеджеры могли сами выбирать ресурсы и блоки без кода, как это сделать я описал здесь.
FastDevLab
Сегодня в 11:10
modx.pro
195
+1
Поблагодарить автора Отправить деньги

Комментарии: 6

Андрей Шевяков
Сегодня в 11:18
0
Вот так же можно выводить из коробки:
{'!PageBlocks' | snippet : [
    'where' => [
        'model_id' => $_modx->resource.parent, // id нужного ресурса
        'constructor_id' => '11', // id блока из списка созданных блоков 
    ],
]}
    FastDevLab
    Сегодня в 11:27
    0
    Выводит только 1 блок (даже если указываешь, несколько) — получается не совсем то
      Андрей Шевяков
      Сегодня в 11:30
      +2
      Можно как то так попробовать для нескольких блоков:
      {'!PageBlocks' | snippet : [
          'where' => [
              'model_id' => $_modx->resource.parent,
              'constructor_id:IN' => [11,12,13]
          ]
      ]}
        Андрей Шевяков
        Сегодня в 11:30
        0
        Возможно немного не правильный синтаксис, но суть понятна, где то я делал так в каких то проектах, работало 100%
          FastDevLab
          Сегодня в 11:34
          0
          Ну вот, зря время тратил) Работает ваш вариант)
            FastDevLab
            9 часов назад
            0
            Хотя не зря, все равно мой велосипед более гибкий, в будущем может еще что то к нему прикручу.
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    6