Битрикс. Создание комплексного компонента. Часть 4 из 4

29.09.2018

Теги: CMSWeb-разработкаБитриксИнфоблокКомпонентРазделИнфоблокаШаблонКомпонентаЭлементИнфоблока

Исходный код нативных компонентов содержит множество переменных, назначение которых не всегда понятно. К сожалению, разработчики Битрикс не пишут комментариев, да и документация оставляет желать много лучшего. Очень часто после прочтения так называемой «документации» появляется больше вопросов, чем ответов. Здесь я постарался подробно разобрать назначение тех переменных, которые могут встретиться при чтении кода.

Чтобы упростить задачу, я разделил файл component.php на два файла поменьше. Один подключается, когда включен режим поддержки ЧПУ, а второй — когда выключен.

<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die();

// require 'component-single.php';

if ($arParams['SEF_MODE'] == 'Y') {
    require 'support-sef-url.php'; // включен режим поддержки ЧПУ
} else {
    require 'without-sef-url.php'; // не включен режим поддержки ЧПУ
}

Файл local/components/tokmakov/iblock/without-sef-url.php:

<?php
/*
 * Файл local/components/tokmakov/iblock/without-sef-url.php
 */
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die();

/*
 * Если не включен режим поддержки ЧПУ
 */

/*
 * В этой переменной будем накапливать значения истинных переменных, восстанавливая их из псевдонимов.
 */
$arVariables = array();

Это самая «главная» переменная комплексного компонента. В конечном счете именно она будут записана в массив $arResult — как результат работы комплексного компонента. И она будет доступна в файлах element.php, section.php и popular.php, которые будут подключены, после того, как отработает component.php.

Переменные $arComponentVariables и $arVariableAliases вспомогательные — они вообще не хранят значения, а лишь имена и псевдонимы. В переменной $arComponentVariables мы указываем ключи массива $_REQUEST, которые должны попасть в $arVariables. В переменной $arVariableAliases мы указываем псевдонимы для «настоящих» имен переменных.

Простой компонент iblock.element ждет, что ему будет передан параметр ELEMENT_ID или ELEMENT_CODE. Простой компонент iblock.section ждет, что ему будет передан параметр SECTION_ID или SECTION_CODE. Это и есть «настоящие» имена переменных, с другими переменными простые компоненты работать не умеют. Если не использовать псевдонимы, то URL страницы комплексного компонента может быть только таким

/test/index.php?SECTION_ID=28
/test/index.php?SECTION_CODE=dogs
/test/index.php?ELEMENT_ID=495
/test/index.php?ELEMENT_CODE=buldog

И мы просто говорим, что надо взять значения из $_REQUEST:

$arComponentVariables = array(
    'ELEMENT_ID',
    'ELEMENT_CODE',
    'SECTION_ID',
    'SECTION_CODE',
);

Если мы хотим изменить имена переменных, мы задаем их псевдонимы.

/test/index.php?SID=28
/test/index.php?SCODE=dogs
/test/index.php?EID=495
/test/index.php?ECODE=buldog

В конечном счете массив $arVariableAliases будет таким:

$arVariableAliases = array(
    'ELEMENT_ID' => 'EID',
    'ELEMENT_CODE' => 'ECODE',
    'SECTION_ID' => 'SID',
    'SECTION_CODE' => 'SCODE'
);

Но такой вид он примет не сразу, а после вызова

$arVariableAliases = CComponentEngine::MakeComponentVariableAliases(
    $arDefaultVariableAliases,    // массив псевдонимов переменных по умолчанию
    $arParams['VARIABLE_ALIASES'] // массив псевдонимов из входных параметров
);

А массив $arDefaultVariableAliases мы должны задать сами — на тот случай, если $arParams['VARIABLE_ALIASES'] окажется пустым. По сути, при вызове этого метода происходит следующее:

$arVariableAliases = array_merge($arDefaultVariableAliases, $arParams['VARIABLE_ALIASES']);

При написании своих компонентов достаточно инициировать эти переменные и больше о них не вспоминать:

$arComponentVariables = array();
$arDefaultVariableAliases = array();
/*
 * Массив имен переменных, которые компонент может получать из запроса. Все переменные, перечисленные
 * в этом массиве, будут добавлены в $arVariables, если они есть в массиве $_REQUEST. Нам есть смысл
 * добавить в этот массив переменную ACTION, которая нам нужна, чтобы знать — какой простой компонент
 * нужно подключать. 
 */
$arComponentVariables = array('ACTION');

Возможно, есть смысл еще добавить в этот массив переменные ELEMENT_ID, ELEMENT_CODE, SECTION_ID, SECTION_CODE — чтобы они гарантированно попали в $arVariables. Наш комплексный компонент сохранит работоспособность, если по каким-то причинам $arVariableAliases окажется пустым, см. ниже по коду вызов CComponentEngine::InitComponentVariables().

$arComponentVariables = array(
    'ELEMENT_ID',
    'ELEMENT_CODE',
    'SECTION_ID',
    'SECTION_CODE',
    'ACTION'
);
/*
 * Массив $arDefaultVariableAliases предназначен для задания псевдонимов «по-умолчанию» переменных в
 * режиме не ЧПУ. В случае, если необходимо, чтобы в HTTP запросе (в адресе страницы) переменная называлась
 * по другому, можно задать псевдоним этой переменной, а при работе компонента восстанавливать значение
 * переменной из псевдонима. Следует помнить, что псевдонимы «по-умолчанию» будут перезаписаны значениями
 * из массива $arParams['VARIABLE_ALIASES'].
 */
$arDefaultVariableAliases = array();

Возможно, есть смысл еще добавить в этот массив переменные ELEMENT_ID, ELEMENT_CODE, SECTION_ID, SECTION_CODE — чтобы они гарантированно попали в $arVariables. Наш комплексный компонент сохранит работоспособность, если по каким-то причинам $arParams['VARIABLE_ALIASES'] окажется пустым.

$arDefaultVariableAliases = array(
    'ELEMENT_ID' => 'ELEMENT_ID',
    'ELEMENT_CODE' => 'ELEMENT_CODE',
    'SECTION_ID' => 'SECTION_ID',
    'SECTION_CODE' => 'SECTION_CODE',
);

Если в визуальном редакторе не задавать псевдонимы переменных, будет сформирован такой вызов компонента:

$APPLICATION->IncludeComponent(
    'tokmakov:iblock',
    '',
    array(
        /*...*/
        'VARIABLE_ALIASES' => array(
            'ELEMENT_ID' => 'ELEMENT_ID',
            'ELEMENT_CODE' => 'ELEMENT_CODE',
            'SECTION_ID' => 'SECTION_ID',
            'SECTION_CODE' => 'SECTION_CODE',
        )
        /*...*/
    )
);

Если в визуальном редакторе задать псевдонимы для переменных, то вызов будет таким:

$APPLICATION->IncludeComponent(
    'tokmakov:iblock',
    '',
    array(
        /*...*/
        'VARIABLE_ALIASES' => array(
            'ELEMENT_ID' => 'EID',
            'ELEMENT_CODE' => 'ECODE',
            'SECTION_ID' => 'SID',
            'SECTION_CODE' => 'SCODE',
        )
        /*...*/
    )
);
/*
 * Соберем массив псевдонимов переменных из массива псевдонимов «по-умолчанию» $arDefaultVariableAliases и
 * массива, переданого во входных параметрах $arParams['VARIABLE_ALIASES']. По сути, происходит следующее
 * $arVariableAliases = array_merge($arDefaultVariableAliases, $arParams['VARIABLE_ALIASES']);
 */
$arVariableAliases = CComponentEngine::MakeComponentVariableAliases(
    $arDefaultVariableAliases,    // массив псевдонимов переменных по умолчанию
    $arParams['VARIABLE_ALIASES'] // массив псевдонимов из входных параметров
);
/*
 * Добавим в $arVariables переменные из $_REQUEST, которые есть в $arComponentVariables и в $arVariableAliases.
 * Переменные из $arComponentVariables просто добавляются в $arVariables, если они есть в $_REQUEST. Переменные 
 * из $arVariableAliases добавляютcя под своими реальными именами, если в $_REQUEST есть соответствующий псевдоним.
 */
CComponentEngine::InitComponentVariables(
    false,                 // в режиме не ЧПУ всегда false
    $arComponentVariables, // массив имен переменных, которые компонент может получать из запроса
    $arVariableAliases,    // массив псевдонимов переменных
    $arVariables           // массив, в котором возвращаются восстановленные переменные
);

Что происходит внутри CComponentEngine::InitComponentVariables():

// Если не существует $arVariables['ELEMENT_ID'], но существуют $arVariableAliases['ELEMENT_ID'] = 'EID' и
// $_REQUEST['EID'] — в массив $arVariables добавляется элемент $arVariables['ELEMENT_ID'] = $_REQUEST['EID']
foreach ($arVariableAliases as $variableName => $aliasName) {
    if (!array_key_exists($variableName, $arVariables)) {
        if (is_string($aliasName) && array_key_exists($aliasName, $_REQUEST)) {
            $arVariables[$variableName] = $_REQUEST[$aliasName];
        }
    }
}
// Если не существует $arVariables['ELEMENT_ID'], но существуют $arComponentVariables['ELEMENT_ID'] и $_REQUEST['ELEMENT_ID'],
// то в массив $arVariables добавляется элемент $arVariables['ELEMENT_ID'] = $_REQUEST['ELEMENT_ID']
if ($arComponentVariables && is_array($arComponentVariables)) {
    for ($i = 0; $i < count($arComponentVariables); $i++) {
        if (!array_key_exists($arComponentVariables[$i], $arVariables) && array_key_exists($arComponentVariables[$i], $_REQUEST)) {
            $arVariables[$arComponentVariables[$i]] = $_REQUEST[$arComponentVariables[$i]];
        }
    }
}
/*
 * Теперь определяем, какую страницу шаблона компонента нужно показать
 */
$componentPage = 'popular';
if (isset($arVariables['ACTION']) && $arVariables['ACTION'] == 'element') {
    $componentPage = 'element'; // элемент инфоблока
}
if (isset($arVariables['ACTION']) && $arVariables['ACTION'] == 'section') {
    $componentPage = 'section'; // раздел инфоблока
}
/*
 * Обрабытываем ситуацию, когда переданы некорректные параметры SECTION_ID, SECTION_CODE, ELEMENT_ID,
 * ELEMENT_CODE и показываем страницу 404 Not Found
 */
$notFound = false;
// недопустимое значение идентификатора элемента
if ($componentPage == 'element') {
    if ($arParams['USE_CODE_INSTEAD_ID'] == 'Y') { // если используются символьные коды
        if ( ! (isset($arVariables['ELEMENT_CODE']) && strlen($arVariables['ELEMENT_CODE']) > 0)) {
            $notFound = true;
        }
    } else { // если используются идентификаторы
        if ( ! (isset($arVariables['ELEMENT_ID']) && ctype_digit($arVariables['ELEMENT_ID']))) {
            $notFound = true;
        }
    }
}
// недопустимое значение идентификатора раздела
if ($componentPage == 'section') {
    if ($arParams['USE_CODE_INSTEAD_ID'] == 'Y') { // если используются символьные коды
        if ( ! (isset($arVariables['SECTION_CODE']) && strlen($arVariables['SECTION_CODE']) > 0)) {
            $notFound = true;
        }
    } else { // если используются идентификаторы
        if ( ! (isset($arVariables['SECTION_ID']) && ctype_digit($arVariables['SECTION_ID']))) {
            $notFound = true;
        }
    }
}
// показываем страницу 404 Not Found
if ($notFound) {
    \Bitrix\Iblock\Component\Tools::process404(
        trim($arParams['MESSAGE_404']) ?: 'Элемент или раздел инфоблока не найден',
        true,
        $arParams['SET_STATUS_404'] === 'Y',
        $arParams['SHOW_404'] === 'Y',
        $arParams['FILE_404']
    );
    return;
}
$arResult['VARIABLES'] = $arVariables;
$arResult['FOLDER'] = '';
if ($arParams['USE_CODE_INSTEAD_ID'] == 'Y') { // если используются символьные коды
    $arResult['SECTION_URL'] =
        $APPLICATION->GetCurPage().'?ACTION=section'.'&'.$arVariableAliases['SECTION_CODE'].'=#SECTION_CODE#';
    $arResult['ELEMENT_URL'] =
        $APPLICATION->GetCurPage().'?ACTION=element'.'&'.$arVariableAliases['ELEMENT_CODE'].'=#ELEMENT_CODE#';
} else { // если используются идентификаторы
    $arResult['SECTION_URL'] = 
        $APPLICATION->GetCurPage().'?ACTION=section'.'&'.$arVariableAliases['SECTION_ID'].'=#SECTION_ID#';
    $arResult['ELEMENT_URL'] =
        $APPLICATION->GetCurPage().'?ACTION=element'.'&'.$arVariableAliases['ELEMENT_ID'].'=#ELEMENT_ID#';
}

$this->IncludeComponentTemplate($componentPage);

Файл local/components/tokmakov/iblock/support-sef-url.php:

<?php
/*
 * Файл local/components/tokmakov/iblock/support-sef-url.php
 */
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED!==true) die();

/*
 * Если включен режим поддержки ЧПУ
 */

/*
 * В этой переменной будем накапливать значения истинных переменных, восстанавливая их из шаблонов
 * путей и из псевдонимов.
 */
$arVariables = array();
/*
 * Массив имен переменных, которые компонент может получать из запроса. Все переменные, перечисленные
 * в этом массиве, будут добавлены в $arVariables, если они есть в массиве $_REQUEST.
 */
$arComponentVariables = array();

Кроме переменных ELEMENT_ID, ELEMENT_CODE, SECTION_ID, SECTION_CODE могут быть переданы дополнительные переменные, например

server.com/demo/category/id/28/?sort=date&dir=desc

Переменная SECTION_ID будет получена из сопоставления шаблона category/id/#SECTION_ID#/. Но здесь для страницы раздела инфоблока переданы параметры сортировки списка элементов: по дате, по убыванию. Наш простой компонент iblock.section этого делать не умеет, но это не трудно реализовать. В массиве $arComponentVariables мы должны описать эти переменные:

$arComponentVariables = array(
    'sort',
    'dir'
);

чтобы они были добавлены в $arVariables и переданы дальше простому компоненту примерно так:

$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    Array(
        /*...*/
        // по какому полю сортировать элементы
        'ELEMENT_SORT_FIELD' => $arResult['VARIABLES']['sort'],
        // направление сортировки — по возрастанию или убыванию
        'ELEMENT_SORT_DIR' => $arResult['VARIABLES']['dir'],
        /*...*/
    ),
    $component
);
/*
 * Массив $arDefaultVariableAliases404 предназначен для задания псевдонимов переменных «по-умолчанию»
 * в режиме ЧПУ. В случае, если необходимо, чтобы в HTTP запросе (в адресе страницы) переменная называлась
 * по другому, можно задать псевдоним этой переменной, а при работе компонента восстанавливать значение
 * переменной из псевдонима. Следует помнить, что псевдонимы «по-умолчанию» будут перезаписаны значениями
 * из массива $arParams['VARIABLE_ALIASES'].
 */
$arDefaultVariableAliases404 = array();

Чтобы продемонстрировать использование массива $arDefaultVariableAliases404, добавим в него элемент ELEMENT_COUNT, который позволяет передать количество элементов инфоблока на странице при постраничной навигации:

$arDefaultVariableAliases404 = array(
    'section' => array(
        'ELEMENT_COUNT' => 'count',
    ),
);

В итоге, после вызова CComponentEngine::InitComponentVariables() ниже по коду, в массив $arVariables будет добавлена переменная ELEMENT_COUNT, значение которой будет получено из $_REQUEST['count']. Мы можем передать эту переменную простому компоненту:

/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'ELEMENT_COUNT' => $arResult['VARIABLES']['ELEMENT_COUNT'] ?: $arParams['SECTION_ELEMENT_COUNT'],
        /*...*/
    ),
    $component
);
/*
 * Массив шаблонов путей «по-умолчанию» для работы в ЧПУ-режиме. Задает имена файлов шаблонов, которые
 * будут запущены в работу, если совпадет шаблон пути. Эти шаблоны путей будут перезаписаны значениями
 * из массива $arParams["SEF_URL_TEMPLATES"]. Массив $arDefaultUrlTemplates404 нужен исключительно на
 * тот случай, если по каким-либо причинам массив $arParams["SEF_URL_TEMPLATES"] окажется пустым.
 */
if ($arParams['USE_CODE_INSTEAD_ID'] == 'Y') { // если используются символьные коды
    $arDefaultUrlTemplates404 = array(
        'popular' => '',
        'section' => 'category/code/#SECTION_CODE#/',
        'element' => 'item/code/#ELEMENT_CODE#/',
    );
} else { // если используются идентификаторы
    $arDefaultUrlTemplates404 = array(
        'popular' => '',
        'section' => 'category/id/#SECTION_ID#/',
        'element' => 'item/id/#ELEMENT_ID#/',
    );
}
/*
 * Определим, каким в итоге будет массив шаблонов путей. По факту, происходит слияние массивов
 * $arUrlTemplates = array_merge($arDefaultUrlTemplates404, $arParams['SEF_URL_TEMPLATES'])
 */
$arUrlTemplates = CComponentEngine::MakeComponentUrlTemplates(
    $arDefaultUrlTemplates404,
    $arParams['SEF_URL_TEMPLATES']
);
/*
 * Соберем массив псевдонимов переменных из массива псевдонимов «по-умолчанию» $arDefaultVariableAliases404
 * и массива, переданого во входных параметрах $arParams['VARIABLE_ALIASES']. По сути, происходит слияние
 * массивов $arVariableAliases = array_merge($arDefaultVariableAliases, $arParams['VARIABLE_ALIASES']);
 */
$arVariableAliases = CComponentEngine::MakeComponentVariableAliases(
    $arDefaultVariableAliases404,
    $arParams['VARIABLE_ALIASES']
);
/*
 * Определим файл шаблона (popular, section, element), который нужно подключить. Заодно получим значения
 * 1. SECTION_ID или SECTION_CODE, если запрошена страница раздела инфоблока
 * 2. ELEMENT_ID или ELEMENT_CODE, если запрошена страница элемента инфоблока
 * Переменная $arVariables передается по ссылке, поэтому на выходе будет содержать значения переменных:
 * server.com/demo/category/id/28/ => $arVariables = array(SECTION_ID => 28)
 * server.com/demo/item/id/97/ => $arVariables = array(ELEMENT_ID => 97)
 */
$componentPage = CComponentEngine::ParseComponentPath(
    $arParams['SEF_FOLDER'],
    $arUrlTemplates, 
    $arVariables
);
/*
 * Метод CComponentEngine::ParseComponentPath() не обрабатывает случай, когда шаблон пути равен пустой
 * строке, например 'popular' => ''. Поэтому делаем это сами
 */
if ($componentPage === false && parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == $arParams['SEF_FOLDER']) {
    $componentPage = 'popular';
}
// Если определить файл шаблона не удалось, показываем  страницу 404 Not Found
if (empty($componentPage)) {
    \Bitrix\Iblock\Component\Tools::process404(
        trim($arParams['MESSAGE_404']) ?: 'Элемент или раздел инфоблока не найден',
        true,
        $arParams['SET_STATUS_404'] === 'Y',
        $arParams['SHOW_404'] === 'Y',
        $arParams['FILE_404']
    );
    return;
}
/*
 * Обрабытываем ситуацию, когда переданы некорректные параметры SECTION_ID, SECTION_CODE, ELEMENT_ID,
 * ELEMENT_CODE и показываем страницу 404 Not Found
 */
$notFound = false;
// недопустимое значение идентификатора элемента
if ($componentPage == 'element') {
    if ($arParams['USE_CODE_INSTEAD_ID'] == 'Y') { // если используются символьные коды
        if ( ! (isset($arVariables['ELEMENT_CODE']) && strlen($arVariables['ELEMENT_CODE']) > 0)) {
            $notFound = true;
        }
    } else { // если используются идентификаторы
        if ( ! (isset($arVariables['ELEMENT_ID']) && ctype_digit($arVariables['ELEMENT_ID']))) {
            $notFound = true;
        }
    }
}
// недопустимое значение идентификатора раздела
if ($componentPage == 'section') {
    if ($arParams['USE_CODE_INSTEAD_ID'] == 'Y') { // если используются символьные коды
        if ( ! (isset($arVariables['SECTION_CODE']) && strlen($arVariables['SECTION_CODE']) > 0)) {
            $notFound = true;
        }
    } else { // если используются идентификаторы
        if ( ! (isset($arVariables['SECTION_ID']) && ctype_digit($arVariables['SECTION_ID']))) {
            $notFound = true;
        }
    }
}
// показываем страницу 404 Not Found
if ($notFound) {
    \Bitrix\Iblock\Component\Tools::process404(
        trim($arParams['MESSAGE_404']) ?: 'Элемент или раздел инфоблока не найден',
        true,
        $arParams['SET_STATUS_404'] === 'Y',
        $arParams['SHOW_404'] === 'Y',
        $arParams['FILE_404']
    );
    return;
}
/*
 * Добавим в $arVariables переменные из $_REQUEST, которые есть в $arComponentVariables и в $arVariableAliases.
 * Переменные из $arComponentVariables просто добавляются в $arVariables, если они есть в $_REQUEST. Переменные из
 * $arVariableAliases добавляютcя под своими реальными именами, если в $_REQUEST есть соответствующий псевдоним.
 */
CComponentEngine::InitComponentVariables(
    $componentPage,
    $arComponentVariables,
    $arVariableAliases,
    $arVariables
);

Если были заданы значения переменных $arComponentVariables и $arDefaultVariableAliases404

$arComponentVariables = array(
    'sort',
    'dir'
);
$arDefaultVariableAliases404 = array(
    'section' => array(
        'ELEMENT_COUNT' => 'count',
    ),
);

и была запрошена страница

server.com/demo/category/id/28/?count=3&sort=date&dir=desc

то перемнная $arVariables будет такой:

$arVariables = array (
    'SECTION_ID' => 28,
    'ELEMENT_COUNT' => 3,
    'sort' => 'date',
    'dir' => 'desc'
);
$arResult['VARIABLES'] = $arVariables;
$arResult['FOLDER'] = $arParams['SEF_FOLDER'];
$arResult['SECTION_URL'] = $arParams['SEF_FOLDER'].$arParams['SEF_URL_TEMPLATES']['section'];
$arResult['ELEMENT_URL'] = $arParams['SEF_FOLDER'].$arParams['SEF_URL_TEMPLATES']['element'];

$this->IncludeComponentTemplate($componentPage);
Обратите внимание, что при размещении комплексного компонента в режиме ЧПУ на странице /test/index.php, файл urlrewrite.php в корне сервера будет перезаписан и в нем появится запись:

<?php
$arUrlRewrite = array(
    0 => 
    array (
        'CONDITION' => '#^/test/#',
        'RULE' => '',
        'ID' => 'tokmakov:iblock',
        'PATH' => '/test/index.php',
        'SORT' => 100,
    ),
);

Когда мы будем обращаться по адресам

/test/category/id/28/
/test/item/id/347/

которые физически не существуют, но соответствуют шаблону #^/test/# — отвечать на обращения будет скрипт /test/index.php, который содержит вызов комплексного компонента tokmakov:iblock.

Вместо заключения

После разбора того, как работает комплексный компонент, все равно остались вопросы:

В режиме без поддержки ЧПУ

1. Зачем нужна переменная $arDefaultVariableAliases, если она перезаписывается значениями из $arParams['VARIABLE_ALIASES']? Если только исключить из файла настроек компонента VARIABLE_ALIASES и использовать $arDefaultVariableAliases, тем самым жестко прописав псевдонимы переменных в component.php. Но тогда изменить это может только программист, а администратор сайта никак на это повлиять не сможет.

2. Зачем нужна переменная $arComponentVariables, которая сообщает, какие переменные из $_REQUEST должны попасть в $arVariables. Зачем вообще нужно эти переменные сначала помещать в массив $arVariables, чтобы потом передать их простым компонентам:

/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'ELEMENT_COUNT' => $arResult['VARIABLES']['count'],
        /*...*/
    )
);

Ведь можно просто в local/components/tokmakov/iblock/templates/.default/section.php написать

/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'ELEMENT_COUNT' => isset($_REQUEST['count']) ? $_REQUEST['count'] : $arParams['SECTION_ELEMENT_COUNT'],
        /*...*/
    )
);

3. С псевдонимами переменных тоже не очень понятно. Зачем вообще было огород городить? Сейчас мы делаем так

/*
 * Файл local/components/tokmakov/iblock/.parameters.php
 */
$arComponentParameters = array(
    'GROUPS' => array(/*...*/),
    'PARAMETERS' => array(
        /*...*/
        'VARIABLE_ALIASES' => array(
            'SECTION_ID' => array('NAME' => 'Идентификатор раздела'),
            'SECTION_CODE' => array('NAME' => 'Символьный код раздела'),
            'ELEMENT_ID' => array('NAME' => 'Идентификатор элемента'),
            'ELEMENT_CODE' => array('NAME' => 'Символьный код элемента'),
        ),
        /*...*/
    )
);

Если мы зададим псевдонимы SID, SCODE, EID, ECODE, после нажатия кнопки «Сохранить» в визуальном редакторе, Битрикс сформирует вызов компонента

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Статьи о домашних животных");
?>
<?php
$APPLICATION->IncludeComponent(
    'tokmakov:iblock',
    '',
    array(
        /*...*/
        'VARIABLE_ALIASES' => array(
            'ELEMENT_CODE' => 'ECODE',
            'ELEMENT_ID' => 'EID',
            'SECTION_CODE' => 'SCODE',
            'SECTION_ID' => 'SID'
        ),
        /*...*/
    )
);
?>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>

Дальше мы восстанавливаем истинные переменные, чтобы передать их при вызове простых компонентов:

/*
 * Файл local/components/tokmakov/iblock/templates/.default/element.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.element',
    '',
    array(
        /*...*/
        'ELEMENT_ID' => $arResult['VARIABLES']['ELEMENT_ID'],     // идентификатор элемента инфоблока
        'ELEMENT_CODE' => $arResult['VARIABLES']['ELEMENT_CODE'], // символьный код элемента инфоблока
        /*...*/
    ),
    $component
);
/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'SECTION_ID' => $arResult['VARIABLES']['SECTION_ID'],     // идентификатор раздела инфоблока
        'SECTION_CODE' => $arResult['VARIABLES']['SECTION_CODE'], // символьный код раздела инфоблока
        /*...*/
    ),
    $component
);

Но если мы удалим VARIABLE_ALIASES из $arComponentParameters['PARAMETERS'], а вместо этого добавим

/*
 * Файл local/components/tokmakov/iblock/.parameters.php
 */
$arComponentParameters = array(
    'GROUPS' => array(/*...*/),
    'PARAMETERS' => array(
        /*...*/
        'SECTION_ID' => array( // идентификатор раздела
            'PARENT' => 'BASE',
            'NAME' => 'Идентификатор раздела',
            'TYPE' => 'STRING',
            'DEFAULT' => '={$_REQUEST["SID"]}',
        ),
        'SECTION_CODE' => array( // символьный код раздела
            'PARENT' => 'BASE',
            'NAME' => 'Символьный код раздела',
            'TYPE' => 'STRING',
            'DEFAULT' => '={$_REQUEST["SCODE"]}',
        ),
        'ELEMENT_ID' => array( // идентификатор элемента
            'PARENT' => 'BASE',
            'NAME' => 'Идентификатор элемента',
            'TYPE' => 'STRING',
            'DEFAULT' => '={$_REQUEST["EID"]}',
        ),
        'ELEMENT_CODE' => array( // символьный код элемента
            'PARENT' => 'BASE',
            'NAME' => 'Символьный код элемента',
            'TYPE' => 'STRING',
            'DEFAULT' => '={$_REQUEST["ECODE"]}',
        ),
        /*...*/
    )
);

после нажатия кнопки «Сохранить» в визуальном редакторе, Битрикс сформирует такой вызов компонента

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Статьи о домашних животных");
?>
<?php
$APPLICATION->IncludeComponent(
    'tokmakov:iblock',
    '',
    array(
        /*...*/
        'ELEMENT_ID' => $_REQUEST['EID'],
        'ELEMENT_CODE' => $_REQUEST['ECODE'],
        'SECTION_CODE' => $_REQUEST['SCODE'],
        'SECTION_ID' => $_REQUEST['SID'],
        /*...*/
    )
);
?>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>

То тем самым получим соответствие

$arParams['SECTION_ID'] = $_REQUEST['SID']
$arParams['SECTION_CODE'] = $_REQUEST['SCODE']
$arParams['ELEMENT_ID'] = $_REQUEST['EID']
$arParams['ELEMENT_CODE'] = $_REQUEST['ECODE']

А при вызове простых компонетов напишем:

/*
 * Файл local/components/tokmakov/iblock/templates/.default/element.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.element',
    '',
    array(
        /*...*/
        'ELEMENT_ID' => $arParams['ELEMENT_ID'],     // идентификатор элемента инфоблока
        'ELEMENT_CODE' => $arParams['ELEMENT_CODE'], // символьный код элемента инфоблока
        /*...*/
    ),
    $component
);
/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'SECTION_ID' => $arParams['SECTION_ID'],     // идентификатор раздела инфоблока
        'SECTION_CODE' => $arParams['SECTION_CODE'], // символьный код раздела инфоблока
        /*...*/
    ),
    $component
);

В режиме с поддержкой ЧПУ

1. Зачем нужна переменная $arDefaultVariableAliases404? В режиме поддержки ЧПУ псевдонимы переменных через визуальный редактор вовсе передать нельзя, они не попадают в код вызова компонента. Определяя эту переменную, мы «зашиваем» в код компонента псевдонимы, которые администратор сайта не сможет переопределить. Только программист сможет дописать в код вызова компонента параметр VARIABLE_ALIASES.

2. Зачем нужна переменная $arComponentVariables — та же проблема, что и для режима без поддержки ЧПУ. Зачем наводить тень на плетень с передачей значений из $_REQUEST в $arVariables, а потом с передачей значений из $arVariables в простой компонент? Сейчас мы делаем так

/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'ELEMENT_COUNT' => $arResult['VARIABLES']['count'],
        /*...*/
    )
);

А можно просто в local/components/tokmakov/iblock/templates/.default/section.php написать

/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'ELEMENT_COUNT' => isset($_REQUEST['count']) ? $_REQUEST['count'] : $arParams['SECTION_ELEMENT_COUNT'],
        /*...*/
    )
);

3. С псевдонимами переменных еще более непонятно, чем в режиме без ЧПУ. Визуальный редактор при включении режима ЧПУ формирует вызов компонента вообще без параметра VARIABLE_ALIASES:

<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
$APPLICATION->SetTitle("Статьи о домашних животных");
?>
<?php
$APPLICATION->IncludeComponent(
    'tokmakov:iblock',
    '',
    array(
        /*...*/
        'SEF_MODE' => 'Y',
        'SEF_URL_TEMPLATES' => array(
            'element'=>'item/id/#ELEMENT_ID#/',
            'section'=>'category/id/#SECTION_ID#/',
            'popular'=>'',
        ),
        /*...*/
    )
);
?>
<?php
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/footer.php");
?>

Потому что переменные мы получаем из шаблона пути SEF_URL_TEMPLATES. «Восстановить» мы можем только переменные из QUERY_STRING, если запрошена страница типа

http://server.com/demo/category/id/28/?count=3

Здесь из шаблона пути будет получена переменная SECTION_ID=28. Хитрыми манипуляциями мы можем из $_REQUEST['count'] сделать $arVariables['ELEMENT_COUNT'], чтобы в дальнейшем передать эту переменную простому компоненту:

/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'ELEMENT_COUNT' => $arResult['VARIABLES']['ELEMENT_COUNT'] ?: $arParams['SECTION_ELEMENT_COUNT'],
        /*...*/
    )
);

А могли бы сделать просто, не связываясь с псевдонимами

/*
 * Файл local/components/tokmakov/iblock/templates/.default/section.php
 */
$APPLICATION->IncludeComponent(
    'tokmakov:iblock.section',
    '',
    array(
        /*...*/
        'ELEMENT_COUNT' => isset($_REQUEST['count']) ? $_REQUEST['count'] : $arParams['SECTION_ELEMENT_COUNT'],
        /*...*/
    )
);

4. Зачем нужна переменная $arDefaultUrlTemplates404, если она перезаписывается значениями из $arParams['SEF_URL_TEMPLATES']? Если только в настройках компонента вовсе убрать возможность влиять на шаблоны URL, а прописывать их в component.php. Но тогда изменить это сможет только программист, а администратор сайта никак на это повлиять не сможет.

Дополнительно

Поиск: CMS • Web-разработка • Битрикс • Инфоблок • Компонент • Раздел инфоблока • Шаблон компонента • Элемент инфоблока

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.