Полный цикл в digital

Создание комплексного компонента

Готовый код можно скачать в моем репозитории на GitFlic.

Комплексные компоненты необходимо использовать в случаях, когда функционал состоит из нескольких страниц с простыми компонентами:

  1. Более удобно использовать если планируется использовать ЧПУ, но только если все страницы с простыми компонентами имеют первую общую часть url. Например, страница со списком записей раздела имеет маску адреса /test/#SECTION_CODE#/, а страница детального описания имеет маску /test/#SECTION_CODE#/#ELEMENT_CODE#/, неизменяемая общая часть у них, это /news/.
  2. Один раз при разработке комплексного компонента достаточно прописать параметры компонентов и при повторном использовании комплексного компонента, не нужно следить за связью настроек простых компонентов.

Основное отличие комплексного компонента от простого, заключается в структуре шаблона. У простого компонента в шаблоне стандартно подключается template.php, а шаблон комплексного компонента всегда имеет более одного файла и основная задача комплексного компонента, это определение какой конкретно файл шаблона подключить в зависимости от url страницы. Сам комплексный компонент не должен выполнять логику, за это должны отвечать простые компоненты, которые подключаются на конкретной странице шаблона.

При разработке комплексного компонента нужно понимать и учитывать, включен или нет в настройках компонента режим ЧПУ SEF_MODE. После включения ЧПУ в режиме редактирования и сохранения настроек компонента через интерфейс битрикса, добавляется элемент массива с чпу параметрами в массив файл urlrewrite.php. Всеравно нужно проверять этот файл, для добавление/удаления правил в urlrewrite.php.

Структура компонента

  • Папка my_components родительская папка
  • Папка hmarketing в которой расположен комплексный компонент
    • Папка /templates/.default/
      • Файл element.php отвечает за вывод элементов
      • Файл index.php отвечает за вывод стартовой информации
      • Файл section.php отвечает за вывод секций
  • Папка hmarketing.element в которой расположен обычный компонент отвечающий за вывод элементов
    • Папка /templates/.default/
      • Файл template.php шаблон компонента
    • Файл .description.php содержит название, описание компонента и его положение в дереве логического размещения (для редактора). Этот файл должен всегда присутствовать в папке компонента. Его отсутствие не скажется на работе компонента, но размещение компонента через визуальный редактор станет невозможным
    • Файл .parameters.php который содержит описание входных параметров компонента для редактора. Если у компонента есть входные параметры, то этот файл должен присутствовать в папке компонента
    • Файл class.php для поддержки ООП-компонентов
  • Папка hmarketing.index в которой расположен обычный компонент отвечающий за вывод первоначальной информации
    • Папка /templates/.default/
      • Файл template.php шаблон компонента
    • Файл .description.php содержит название, описание компонента и его положение в дереве логического размещения (для редактора). Этот файл должен всегда присутствовать в папке компонента. Его отсутствие не скажется на работе компонента, но размещение компонента через визуальный редактор станет невозможным
    • Файл .parameters.php который содержит описание входных параметров компонента для редактора. Если у компонента есть входные параметры, то этот файл должен присутствовать в папке компонента
    • Файл class.php для поддержки ООП-компонентов
  • Папка hmarketing.section в которой расположен обычный компонент отвечающий за вывод секций
    • Папка /templates/.default/
      • Файл template.php шаблон компонента
    • Файл .description.php содержит название, описание компонента и его положение в дереве логического размещения (для редактора). Этот файл должен всегда присутствовать в папке компонента. Его отсутствие не скажется на работе компонента, но размещение компонента через визуальный редактор станет невозможным
    • Файл .parameters.php который содержит описание входных параметров компонента для редактора. Если у компонента есть входные параметры, то этот файл должен присутствовать в папке компонента
    • Файл class.php для поддержки ООП-компонентов

Вместо файла template.php, в папке шаблона находятся три файла, element.php, section.php, index.php. В зависимости от url комплексный компонент будет подключать один из этих файлов с переменными, которые найдены по url-маске.

Минимальный файл .parameters.php

Параметры компонента для ЧПУ.

my_components/hmarketing/.parameters.php<?
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
// класс для загрузки необходимых файлов, классов, модулей
use Bitrix\Main\Loader;
// проверяем установку модуля «Информационные блоки»
if (!CModule::IncludeModule('iblock')) {
    return;
}
// подключаем модуль «Информационные блоки»
Loader::includeModule('iblock');
// получаем массив всех типов инфоблоков для возможности выбора
$arIBlockType = CIBlockParameters::GetIBlockTypes();
// пустой массив для вывода 
$arInfoBlocks = array();
// выбираем активные инфоблоки
$arFilterInfoBlocks = array('ACTIVE' => 'Y');
// сортируем по озрастанию поля сортировка
$arOrderInfoBlocks = array('SORT' => 'ASC');
// если уже выбран тип инфоблока, выбираем инфоблоки только этого типа
if (!empty($arCurrentValues['IBLOCK_TYPE'])) {
    $arFilterInfoBlocks['TYPE'] = $arCurrentValues['IBLOCK_TYPE'];
}
// метод выборки информационных блоков
$rsIBlock = CIBlock::GetList($arOrderInfoBlocks, $arFilterInfoBlocks);
// перебираем и выводим в адмику доступные информационные блоки
while ($obIBlock = $rsIBlock->Fetch()) {
    $arInfoBlocks[$obIBlock['ID']] = '[' . $obIBlock['ID'] . '] ' . $obIBlock['NAME'];
}
// настройки компонента, формируем массив $arParams
$arComponentParameters = [
    // основной массив с параметрами
    "PARAMETERS" => [
        // псевдоимена для комплексного компонента
        "VARIABLE_ALIASES" => [
            // элемент
            "ELEMENT_CODE" => [
                "NAME" => 'Символьный код элемента',
            ],
            // секция
            "SECTION_CODE" => [
                "NAME" => 'Символьный код раздела',
            ],
            "CATALOG_URL" => [
                "NAME" => 'Каталог (относительно корня сайта)',
            ]
        ],
        // настройки режима ЧПУ
        "SEF_MODE" => [
            // настройки для секции
            "section" => [
                "NAME" => 'Страница раздела',
                "DEFAULT" => "#SECTION_CODE#/",
                "VARIABLES" => [
                    "SECTION_ID",
                    "SECTION_CODE",
                    "SECTION_CODE_PATH",
                ],
            ],
            // настройки для элемента
            "element" => [
                "NAME" => 'Детальная страница',
                "DEFAULT" => "#SECTION_CODE#/#ELEMENT_CODE#/",
                "VARIABLES" => [
                    "ELEMENT_ID",
                    "ELEMENT_CODE",
                    "SECTION_ID",
                    "SECTION_CODE",
                    "SECTION_CODE_PATH",
                ]
            ]
        ],
        // выбор типа инфоблока
        'IBLOCK_TYPE' => array(                  // ключ массива $arParams в component.php
            'PARENT' => 'TEST',                  // название группы
            'NAME' => 'Выберите тип инфоблока',  // название параметра
            'TYPE' => 'LIST',                    // тип элемента управления, в котором будет устанавливаться параметр
            'VALUES' => $arIBlockType,           // входные значения
            'REFRESH' => 'Y',                    // перегружать настройки или нет после выбора (N/Y)
            'DEFAULT' => 'news',                 // значение по умолчанию
            'MULTIPLE' => 'N',                   // одиночное/множественное значение (N/Y)
        ),
        // выбор самого инфоблока
        'IBLOCK_ID' => array(
            'PARENT' => 'BASE',
            'NAME' => 'Выберите родительский инфоблок',
            'TYPE' => 'LIST',
            'VALUES' => $arInfoBlocks,
            'REFRESH' => 'Y',
            "DEFAULT" => '',
            "ADDITIONAL_VALUES" => "Y",
        ),
    ]
];

Минимальный набор для class.php

Определяет какой шаблон подключить и отдача 404 если шаблон не найден.

<?
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) die();
// проверяем установку модуля «Информационные блоки»
if (!CModule::IncludeModule('iblock')) {
    return;
}
// класс для 404 ошибки
use Bitrix\Iblock\Component\Tools;
// класс для загрузки необходимых файлов, классов, модулей
use Bitrix\Main\Loader;
// подключаем приложение для обращения к глобальным сущностям ядра
use \Bitrix\Main\Application,
    \Bitrix\Main\Context,
    \Bitrix\Main\Request;
class ComplexComponent extends CBitrixComponent
{
    // список переменных, которых также нужно получить из GET параметров, но их нет в url-маске. К примеру мы указали маску server.com/test/#SECTION_CODE#/ и в $arComponentVariables указали "SECTION", при парсинге server.com/test/section-code/?SECTION=123 в $arVariables будет SECTION_CODE и SECTION, несмотря на отсутствие SECTION в маске
    protected array $arComponentVariables = [
        'CODE_SECTION'
    ];
    // выполняет основной код компонента, аналог конструктора (метод подключается автоматически)
    public function executeComponent()
    {
        // подключаем модуль «Информационные блоки»
        Loader::includeModule('iblock');
        // если выбран режим поддержки ЧПУ, вызываем метод sefMode()
        if ($this->arParams["SEF_MODE"] === "Y") {
            $componentPage = $this->sefMode();
        }
        // если отключен режим поддержки ЧПУ, вызываем метод noSefMode()
        if ($this->arParams["SEF_MODE"] != "Y") {
            $componentPage = $this->noSefMode();
        }
        // отдаем 404 статус если не найден шаблон
        if (!$componentPage) {
            Tools::process404(
                $this->arParams["MESSAGE_404"],
                ($this->arParams["SET_STATUS_404"] === "Y"),
                ($this->arParams["SET_STATUS_404"] === "Y"),
                ($this->arParams["SHOW_404"] === "Y"),
                $this->arParams["FILE_404"]
            );
        }
        // подключается файл php из папки комплексного компонента по имени файла, если $componentPage=section, значит подключится section.php расположенный по пути templates/.default
        $this->IncludeComponentTemplate($componentPage);
    }
    // метод обработки режима ЧПУ
    protected function sefMode()
    {
        // массив предназначен для обработки HTTP GET запросов из адреса страницы, используется в режиме ЧПУ. Предназначен для задания псевдонимов из массива arParams["SEF_URL_TEMPLATES"] в вызове комплексного компонента, если нужно прокинуть GET параметр server.com/test/?ELEMENT_COUNT=1 дальше в простой компонент, в массив $arDefaultVariableAliases404 нужно добавить псевдоним, указав ключ section/element для передачи в нужный файл section.php/element.php: 'section' => array('ELEMENT_COUNT' => 'ELEMENT_COUNT'). Если нужно, чтобы в адресной строке браузера передача параметра выглядела не так: server.com/test/?ELEMENT_COUNT=1 а вот так: server.com/test/?COUNT=1. Для этого задаем псевдоним 'ELEMENT_COUNT' => 'COUNT'
        $arDefaultVariableAliases404 = [];
        // значение маски для подключения шаблона по умолчанию, section.php, element.php, index.php
        $arDefaultUrlTemplates404 = [
            "section" => "#SECTION_CODE#/",
            "element" => "#SECTION_CODE#/#ELEMENT_CODE#/",
        ];
        // массив будут заполнен переменными, которые будут найдены по маске шаблонов url
        $arVariables = [];
        // объект для поиска шаблонов
        $engine = new CComponentEngine($this);
        // объединение дефолтных параметров масок шаблонов и алиасов которые приходят в arParams["SEF_URL_TEMPLATES"] и из массива $arDefaultUrlTemplates404, для определения какой шаблон section.php, element.php, index.php подключать. Параметры из настроек arrParams заменяют дефолтные
        $arUrlTemplates = CComponentEngine::makeComponentUrlTemplates(
            // массив переменных масок по умолчанию
            $arDefaultUrlTemplates404,
            // массив переменных масок из входных параметров
            $this->arParams["SEF_URL_TEMPLATES"]
        );
        // объединение дефолтных алиасов которые приходят в arParams["VARIABLE_ALIASES"] в вызове комплексного компонента и из массива $arDefaultVariableAliases404, для определения HTTP GET запросов из адреса страницы. Параметры из настроек arrParams заменяют дефолтные
        $arVariableAliases = CComponentEngine::makeComponentVariableAliases(
            // массив псевдонимов переменных по умолчанию
            $arDefaultVariableAliases404,
            // массив псевдонимов из входных параметров
            $this->arParams["VARIABLE_ALIASES"]
        );
        // определение шаблона, какой файл подключать section.php, element.php, index.php
        $componentPage = $engine->guessComponentPath(
            // путь до корня секции
            $this->arParams["SEF_FOLDER"],
            // массив масок
            $arUrlTemplates,
            // путь до секции SECTION_CODE и элемента ELEMENT_CODE
            $arVariables
        );
        // проверяем, если не удалось сопоставить шаблон, значит выводим index.php
        if ($componentPage == FALSE) {
            $componentPage = 'index';
        }
        // получаем значения переменных в $arVariables
        CComponentEngine::initComponentVariables(
            // файл который будет подключен section.php, element.php, index.php
            $componentPage,
            // массив имен переменных, которые компонент может получать из GET запроса
            $this->arComponentVariables,
            // массив псевдонимов переменных из GET запроса
            $arVariableAliases,
            // востановленные переменные
            $arVariables
        );
        // формируем arResult
        $this->arResult = [
            "VARIABLES" => $arVariables,
            "ALIASES" => $arVariableAliases
        ];
        return $componentPage;
    }
    // метод обработки режима без ЧПУ
    protected function noSefMode()
    {
        // переменная в которую запишем название подключаемой страницы
        $componentPage = "";
        // массив предназначен для обработки HTTP GET запросов из адреса страницы, используется в режиме не ЧПУ. Предназначен для задания псевдонимов из массива arParams["VARIABLE_ALIASES"] в вызове комплексного компонента, если нужно прокинуть GET параметр server.com/test/?ELEMENT_ID=1 дальше в простой компонент, в массив $arDefaultVariableAliases нужно добавить псевдоним: 'ELEMENT_ID' => 'ELEMENT_ID'. Если нужно, чтобы в адресной строке браузера передача параметра выглядела не так: server.com/test/?ELEMENT_ID=1 а вот так: server.com/test/?ID=1. Для этого задаем псевдоним 'ELEMENT_ID' => 'ID'
        $arDefaultVariableAliases = [];
        // объединение дефолтных алиасов которые приходят в arParams["VARIABLE_ALIASES"] и из массива $arDefaultVariableAliases, для определения HTTP GET запросов из адреса страницы. Параметры из настроек arrParams заменяют дефолтные
        $arVariableAliases = CComponentEngine::makeComponentVariableAliases(
            // массив псевдонимов переменных по умолчанию
            $arDefaultVariableAliases,
            // массив псевдонимов из входных параметров
            $this->arParams["VARIABLE_ALIASES"]
        );
        // массив будут заполнен переменными, которые будут найдены по маске шаблонов url
        $arVariables = [];
        // получаем значения переменных в $arVariables
        CComponentEngine::initComponentVariables(
            // файл который будет подключен section.php, element.php, index.php, для режима ЧПУ
            false,
            // массив имен переменных, которые компонент может получать из GET запроса
            $this->arComponentVariables,
            // массив псевдонимов переменных из GET запроса
            $arVariableAliases,
            // востановленные переменные
            $arVariables
        );
        // получаем контекст текущего хита
        $context = Application::getInstance()->getContext();
        // получаем объект Request
        $request = $context->getRequest();
        // получаем директорию запрошенной страницы
        $rDir = $request->getRequestedPageDirectory();
        // если запрошенная директория равна переданой в arParams["CATALOG_URL"], определяем тип страницы стартовая 
        if ($arVariableAliases["CATALOG_URL"] == $rDir) {
            $componentPage = "index";
        }
        // по найденным параметрам $arVariables определяем тип страницы элемент
        if ((isset($arVariables["ELEMENT_ID"]) && intval($arVariables["ELEMENT_ID"]) > 0) || (isset($arVariables["ELEMENT_CODE"]) && $arVariables["ELEMENT_CODE"] <> '')) {
            $componentPage = "element";
        }
        // по найденным параметрам $arVariables определяем тип страницы секция
        if ((isset($arVariables["SECTION_ID"]) && intval($arVariables["SECTION_ID"]) > 0) || (isset($arVariables["SECTION_CODE"]) && $arVariables["SECTION_CODE"] <> '')) {
            $componentPage = "section";
        }
        // формируем arResult
        $this->arResult = [
            "VARIABLES" => $arVariables,
            "ALIASES" => $arVariableAliases
        ];
        return $componentPage;
    }
}

Подключение компонента на странице

Подключать будем в разделе /test/ на странице index.php

/test/index.php<?$APPLICATION->IncludeComponent(
	"my_components:hmarketing", 
	".default", 
	array(
		"IBLOCK_ID" => "1",
		"IBLOCK_TYPE" => "news",
		"SEF_MODE" => "Y",
		"COMPONENT_TEMPLATE" => ".default",
		"SEF_FOLDER" => "/test/",
		"SEF_URL_TEMPLATES" => array(
			"section" => "#SECTION_CODE#/",
			"element" => "#SECTION_CODE#/#ELEMENT_CODE#/",
		)
	),
	false
);?>

Не забываем, если подключаем в режиме работы с поддержкой ЧПУ, то нужно в urlrewrite.php прописать правило:

urlrewrite.phparray (
  'CONDITION' => '#^/test/#',
  'RULE' => '',
  'ID' => '',
  'PATH' => '/test/index.php',
  'SORT' => 100,
)

По адресу /test/ подключается файл шаблона index.php с переменными:

Array(
[VARIABLES] => Array
    (
    )

[ALIASES] => Array
    (
    )
)

По адресу /test/section-code/ подключается файл шаблона section.php с переменными:

Array(
[VARIABLES] => Array
    (
        [SECTION_CODE] => section-code
    )

[ALIASES] => Array
    (
    )
)

По адресу /test/section-code/element-code/ подключается файл шаблона element.php с переменными:

Array(
[VARIABLES] => Array
    (
        [SECTION_CODE] => section-code
        [ELEMENT_CODE] => element-code
    )

[ALIASES] => Array
    (
    )
)
Заполните форму уже сегодня!
Для начала сотрудничества необходимо заполнить заявку или заказать обратный звонок. В ответ получите коммерческое предложение, которое будет содержать индивидуальную стратегию с учетом требований и поставленных задач
Работаем по будням с 9:00 до 18:00. Заявки, отправленные в выходные, обрабатываем в первый рабочий день до 12:00.
Спасибо, ваш запрос принят и будет обработан!
Эйч Маркетинг