WT Layout select - плагин выбора файла макета 2026-02-26

Плагин пользовательского поля Joomla: выпадающий список PHP-лейаутов из указанных папок с учетом пер

  1. Сергей Толкачев
    Совместимость с версией Joomla!:
    • 5.x
    Лицензия:
    GPLv2 or later
    Домашняя страница:
    https://web-tolk.ru/
    Скачать:
    https://web-tolk.ru/get?element=wtlayoutselect&utm_source=joomla-support.ru
    Документация:
    https://web-tolk.ru/dev/joomla-plugins/wt-layout-select-joomla-custom-field-plugin
    Оплата:
    • Бесплатное
    Тип расширения:
    • Плагин
    Системные требования:
    Joomla 5+
    Описание

    Плагин добавляет тип пользовательского поля wtlayoutselect.

    Поле Joomla:
    • сканирует указанные папки с PHP-лейаутами;
    • показывает в выпадающем списке варианты с учетом переопределений шаблона (/templates/<template>/html/...);
    • сохраняет выбранное значение в rawvalue поля с layout и basePath (JSON);
    • отдает вычисленное значение в value (layout_id), пригодное для Joomla LayoutHelper::render().

    Зачем это нужно?

    Поле удобно, когда нужно дать контент-менеджеру выбор варианта верстки без правки шаблона:
    • материалы (com_content): секции статьи, карточки, блоки CTA;
    • контакты (com_contact): разные шаблоны карточки контакта;
    • категории и списки: разные макеты частей страницы под контекст;
    • зоны вывода модулей: включение контента/модулей в нужном варианте макета;
    • возможность создавать переиспользуемые блоки вёрстки для создания лендингов на Joomla.
    2 основных варианта использования поля

    Вы используете это поле в своих переопределениях макета материалов, контактов Joomla или тех компонентов, которые их поддерживают.
    Чтобы значение поля не отображалось автоматически, рекомендуется указать это в настройках поля.
    Само поле играет роль логического переключателя макетов частей страницы, и его вывод ($field->value) имеет ценность в первую очередь для разработчика.

    Вариант 1: рендер по вычисленному $field->value
    Код (PHP):
    1. <?php
    2. use Joomla\CMS\Layout\LayoutHelper;
    3.  
    4. $field = $this->item->jcfields[14] ?? null;
    5.  
    6. if ($field && !empty($field->value)) {
    7.     echo LayoutHelper::render($field->value, ['item' => $this->item]);
    8. }


    Или доступ по имени (алиасу) поля:

    Код (PHP):
    1. <?php
    2. defined('_JEXEC') or die;
    3.  
    4. use Joomla\CMS\Factory;
    5. use Joomla\CMS\Layout\LayoutHelper;
    6.  
    7. // Rebuild custom fields by field alias
    8. $customFields = [];
    9. foreach ($this->item->jcfields as $f) {
    10.     $customFields[$f->name] = $f;
    11. }
    12.  
    13. echo LayoutHelper::render(
    14.     layoutFile: $customFields['layout-select']->value,
    15.     displayData: ['item' => $this->item, 'jcfields' => $customFields]
    16. );
    Вариант 2: рендер из rawvalue с basePath
    Код (PHP):
    1. <?php
    2. use Joomla\CMS\Layout\LayoutHelper;
    3.  
    4. $field = $this->item->jcfields[14] ?? null;
    5.  
    6. if ($field && !empty($field->rawvalue)) {
    7.     $raw = json_dephp($field->rawvalue);
    8.  
    9.     if (!empty($raw->layout) && !empty($raw->basePath)) {
    10.         echo LayoutHelper::render($raw->layout, ['item' => $this->item], $raw->basePath);
    11.     }
    12. }
    Как указывать папки в параметрах поля и какой будет вычисленный layout_id

    Ниже примеры для поля wtlayoutselect, если выбран файл pricelist.php.

    Пример 1
    Папка в параметрах поля: layouts/com_content/article/sections
    Где реально лежит файл: JPATH_ROOT/layouts/com_content/article/sections/pricelist.php
    rawvalue (ключевая часть): basePath=layouts/com_content/article/sections, layout=pricelist
    Вычисленный layout_id в $field->value: com_content.article.sections.pricelist

    Пример 2
    Папка в параметрах поля: layouts/com_content/article/sections
    Где реально лежит файл: templates/<template>/html/com_content/article/sections/pricelist.php (override)
    rawvalue (ключевая часть): basePath=layouts/com_content/article/sections, layout=pricelist
    Вычисленный layout_id в $field->value: com_content.article.sections.pricelist

    Пример 3
    Папка в параметрах поля: templates/multizone/html/com_content/article/sections
    Где реально лежит файл: JPATH_ROOT/templates/multizone/html/com_content/article/sections/pricelist.php
    rawvalue (ключевая часть): basePath=templates/multizone/html/com_content/article/sections, layout=pricelist
    Вычисленный layout_id в $field->value: templates.multizone.html.com_content.article.sections.pricelist

    Пример 4
    Папка в параметрах поля: components/com_contact/layouts/contact/parts
    Где реально лежит файл: JPATH_ROOT/components/com_contact/layouts/contact/parts/pricelist.php
    rawvalue (ключевая часть): basePath=components/com_contact/layouts/contact/parts, layout=pricelist
    Вычисленный layout_id в $field->value: components.com_contact.layouts.contact.parts.pricelist

    Важно:
    • Для путей, начинающихся с layouts/..., плагин убирает префикс layouts. в $field->value, чтобы layout_id можно было сразу передавать в LayoutHelper.
    • Для путей вне JPATH_ROOT/layouts (например, templates/... и components/...) layout_id включает весь путь в dot-формате.
    • В таких случаях обычно надежнее рендерить через rawvalue с явным basePath (вариант 2 выше).

    Пример вызова в переопределении материала (/templates/<template>/html/com_content/article/default.php):

    Код (PHP):
    1. <?php
    2. use Joomla\CMS\Layout\LayoutHelper;
    3.  
    4. $field = null;
    5.  
    6. foreach (($this->item->jcfields ?? []) as $f) {
    7.     if (($f->name ?? '') === 'article_layout_variant') {
    8.         $field = $f;
    9.         break;
    10.     }
    11. }
    12.  
    13. if ($field && !empty($field->value)) {
    14.     echo LayoutHelper::render($field->value, ['item' => $this->item]);
    15. }
    Примеры лейаутов: когда передается item материала

    Ниже примеры layout-файлов (например, в layouts/com_content/article/sections/...), когда вы передали ['item' => $this->item].

    Пример 1: базовый layout секции статьи
    Файл: layouts/com_content/article/sections/lead.php

    Код (PHP):
    1. <?php
    2. /** @var array $displayData */
    3.  
    4. defined('_JEXEC') or die;
    5.  
    6. extract($displayData);
    7.  
    8. if (empty($item)) {
    9.     return;
    10. }
    11. ?>
    12. <section class="article-lead">
    13.     <h2><?php echo htmlspecialchars($item->title ?? '', ENT_QUOTES, 'UTF-8'); ?></h2>
    14.  
    15.     <?php if (!empty($item->images)) :
    16.         $images = json_dephp($item->images);
    17.         $intro  = $images->image_intro ?? '';
    18.     ?>
    19.         <?php if (!empty($intro)) : ?>
    20.             <img src="/<?php echo htmlspecialchars($intro, ENT_QUOTES, 'UTF-8'); ?>" alt="">
    21.         <?php endif; ?>
    22.     <?php endif; ?>
    23.  
    24.     <div>
    25.         <?php echo $item->introtext ?? ''; ?>
    26.     </div>
    27. </section>
    Пример 2: как получить поля статьи внутри layout
    Файл: layouts/com_content/article/sections/specs.php

    Код (PHP):
    1. <?php
    2. /** @var array $displayData */
    3.  
    4. defined('_JEXEC') or die;
    5.  
    6. extract($displayData);
    7.  
    8. if (empty($item)) {
    9.     return;
    10. }
    11.  
    12. $fields = $item->jcfields ?? [];
    13. $sku    = null;
    14. $price  = null;
    15.  
    16. foreach ($fields as $f) {
    17.     if (($f->name ?? '') === 'sku') {
    18.         $sku = $f->rawvalue;
    19.     }
    20.  
    21.     if (($f->name ?? '') === 'price') {
    22.         $price = $f->rawvalue;
    23.     }
    24. }
    25. ?>
    26. <div class="product-specs">
    27.     <?php if (!empty($sku)) : ?><p>SKU: <?php echo htmlspecialchars($sku, ENT_QUOTES, 'UTF-8'); ?></p><?php endif; ?>
    28.     <?php if (!empty($price)) : ?><p>Price: <?php echo htmlspecialchars($price, ENT_QUOTES, 'UTF-8'); ?></p><?php endif; ?>
    29. </div>
    Рендер модульной позиции через ModuleHelper в переопределениях Joomla
    Файл: layouts/com_content/article/sections/sidebar-modules.php

    Код (PHP):
    1. <?php
    2. /** @var array $displayData */
    3.  
    4. defined('_JEXEC') or die;
    5.  
    6. use Joomla\CMS\Helper\ModuleHelper;
    7.  
    8. extract($displayData);
    9.  
    10. // При желании можно выбирать позицию по материалу/категории
    11. $position = 'article-sidebar';
    12.  
    13. $modules = ModuleHelper::getModules($position);
    14.  
    15. if (empty($modules)) {
    16.     return;
    17. }
    18. ?>
    19. <aside class="article-sidebar-modules">
    20.     <?php
    21.     // Выводим все модули из этой позиции
    22.     foreach ($modules as $module) : ?>
    23.         <div class="article-sidebar-module">
    24.             <?php echo ModuleHelper::renderModule($module, ['style' => 'none']); ?>
    25.         </div>
    26.     <?php endforeach; ?>
    27. </aside>