Напишем заготовку для создания своего компонента. Объяснений будет по минимуму, многое очень подробно написано в этих ссылках:
-
Запуск ajax-действий в компоненте. BX.ajax.runComponentAction
-
Кастомные (свои) настройки, параметры компонентов в 1С-Битрикс
Структура компонента Битрикс
Напомним себе лишний раз структуру компонента и оставим под рукой.
Создаем папку со своим namespace в папке local/components/ У меня это будет папка kochnev
Далее внутри создаем папку с названием компонента, у меня это будет draft
Теперь добавляем файлы:
Файл .description.php
Содержит описание компонента для отображения в визуальном редакторе Битрикс.
<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true)
{
die();
}
$arComponentDescription = [
'NAME' => GetMessage('K4v_DRAFT_COMPONENT_NAME'),
'DESCRIPTION' => GetMessage('K4v_DRAFT_COMPONENT_DESCRIPTION'),
'ICON' => '/images/search_page.gif',
'CACHE_PATH' => 'Y',
'PATH' => [
'ID' => 'kochnev',
'NAME' => GetMessage('K4v_DRAFT_COMPONENT_CATEGORY')
],
];
Lang файл .description.php local/components/kochnev/draft/lang/ru/.description.php
<?php
$MESS ['K4v_DRAFT_COMPONENT_NAME'] = "Заготовка кастомного компонента";
$MESS ['K4v_DRAFT_COMPONENT_DESCRIPTION'] = "Описание работы кастомного компонента.";
$MESS ['K4v_DRAFT_COMPONENT_CHILD_NAME'] = "Подкатегория кастомного компонента";
$MESS ['K4v_DRAFT_COMPONENT_CATEGORY'] = "Kochnev";
Если компонент не появился в списке, нужно нажать кнопку "Обновить"
Файл .parameters.php
Как формировать этот файл подробно описано в этой статье
<?php
if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
die();
}
$arComponentParameters = [
'GROUPS' => [
'GROUP_SETTINGS' => [
'NAME' => GetMessage('K4v_DRAFT_COMPONENT_SETTINGS'),
],
],
'PARAMETERS' => [
'AJAX_MODE' => [],
'CACHE_TIME' => ['DEFAULT' => 3600],
'DRAFT_PARAMETER_STRING' => [
'PARENT' => 'GROUP_SETTINGS',
'NAME' => GetMessage('K4v_DRAFT_COMPONENT_PARAMETER_STRING'),
'TYPE' => 'STRING',
'DEFAULT' => 'Значение по умолчанию',
],
'DRAFT_PARAMETER_LIST' => [
'PARENT' => 'GROUP_SETTINGS',
'NAME' => GetMessage('K4v_DRAFT_COMPONENT_PARAMETER_CHECKBOX'),
'TYPE' => 'CHECKBOX',
'DEFAULT' => 'N',
],
'DRAFT_PARAMETER_CHECKBOX' => [
'PARENT' => 'GROUP_SETTINGS',
'NAME' => GetMessage('K4v_DRAFT_COMPONENT_PARAMETER_LIST'),
'TYPE' => 'LIST',
"VALUES" => [
1 => GetMessage('K4v_DRAFT_COMPONENT_PARAMETER_LIST_VAL_1'),
2 => GetMessage('K4v_DRAFT_COMPONENT_PARAMETER_LIST_VAL_2'),
3 => GetMessage('K4v_DRAFT_COMPONENT_PARAMETER_LIST_VAL_3'),
],
"MULTIPLE" => "N",
],
],
];
Lang файл .description.php local/components/kochnev/draft/lang/ru/.parameters.php
<?php
$MESS ['K4v_DRAFT_COMPONENT_SETTINGS'] = "Группа настроек";
$MESS ['K4v_DRAFT_COMPONENT_PARAMETER_STRING'] = "Параметр строка";
$MESS ['K4v_DRAFT_COMPONENT_PARAMETER_CHECKBOX'] = "Параметр чекбокс";
$MESS ['K4v_DRAFT_COMPONENT_PARAMETER_LIST'] = "Параметр список";
$MESS ['K4v_DRAFT_COMPONENT_PARAMETER_LIST_VAL_1'] = "Элемент списка 1";
$MESS ['K4v_DRAFT_COMPONENT_PARAMETER_LIST_VAL_2'] = "Элемент списка 2";
$MESS ['K4v_DRAFT_COMPONENT_PARAMETER_LIST_VAL_3'] = "Элемент списка 3";
$MESS ['K4v_DRAFT_COMPONENT_PARAMETER_DEF_STRING'] = "Значение по умолчанию";
После настроек всех параметров, вызов компонента выглядит так
<?$APPLICATION->IncludeComponent(
"kochnev:draft",
"",
Array(
"AJAX_MODE" => "N",
"AJAX_OPTION_ADDITIONAL" => "",
"AJAX_OPTION_HISTORY" => "N",
"AJAX_OPTION_JUMP" => "N",
"AJAX_OPTION_STYLE" => "Y",
"CACHE_TIME" => "3600",
"CACHE_TYPE" => "A",
"DRAFT_PARAMETER_CHECKBOX" => "Y",
"DRAFT_PARAMETER_LIST" => "2",
"DRAFT_PARAMETER_STRING" => "Значение по умолчанию"
)
);?>
Файл class.php
Это сердце нашего компонента. Здесь мы:
-
Подготавливаем параметры.
-
Получаем данные.
-
Подключаем шаблон.
Наследуемся от CBitrixComponent и наш класс подключится автоматически.
<?php
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
die();
}
// Класс для загрузки необходимых файлов, классов, модулей
use Bitrix\Main\Loader;
// Класс для работы с языковыми файлами
use Bitrix\Main\Localization\Loc;
// Класс для всех исключений в системе
use Bitrix\Main\SystemException;
// Класс для вспомогательных методов в системе
use Bitrix\Iblock\Component\Tools;
// Наш собственный класс из папки lib
use Draft\Demo;
class CustomCBitrixComponent extends CBitrixComponent
{
// Выполняет основной код компонента, аналог конструктора (метод подключается автоматически)
public function executeComponent(): void
{
// Если у нас много логики и требуется разносить ее по отдельным классам.
// Регистрируем автозагрузку для нашего пространства имен
Loader::registerAutoLoadClasses(
null,
[
// ключ - имя класса с пространством имен, значение - путь относительно корня сайта к файлу.
Demo::class => '/local/components/kochnev/draft/lib/Demo/Demo.php',
]
);
dump(Demo::test());
try {
// Подключаем метод проверки подключения модуля «Информационные блоки»
$this->checkModules();
// Подключаем метод подготовки массива $arResult
$this->getResult();
} catch (SystemException $e) {
ShowError($e->getMessage());
}
}
// Подключение языковых файлов (метод подключается автоматически)
public function onIncludeComponentLang(): void
{
Loc::loadMessages(__FILE__);
}
// Проверяем установку модуля «Информационные блоки» (метод подключается внутри класса try...catch)
protected function checkModules(): void
{
// Если модуль не подключен
if (!Loader::includeModule('iblock')) // Выводим сообщение в catch
{
throw new SystemException(Loc::getMessage('K4v_DRAFT_COMPONENT_IBLOCK_MODULE_NOT_INSTALLED'));
}
}
// Обработка массива $arParams (метод подключается автоматически)
public function onPrepareComponentParams($arParams)
{
// Время кеширования
if (!isset($arParams['CACHE_TIME'])) {
$arParams['CACHE_TIME'] = 3600;
} else {
$arParams['CACHE_TIME'] = (int) $arParams['CACHE_TIME'];
}
// Покажем исключение о том, что какого-то параметра не хватает
/*if (!isset($arParams['IBLOCK_ID'])) {
throw new SystemException(Loc::getMessage('K4v_DRAFT_COMPONENT_NO_IBLOCK_ID'));
}*/
// Пример с показом ошибка, вместо исключения
if (empty($arParams['DRAFT_PARAMETER_STRING'])) {
ShowError(Loc::getMessage('K4v_DRAFT_COMPONENT_PARAMETER_STRING_EMPTY'));
// Или
// throw new SystemException(Loc::getMessage('K4v_DRAFT_COMPONENT_PARAMETER_STRING_EMPTY'));
}
// Возвращаем в метод новый массив $arParams
return $arParams;
}
// подготовка массива $arResult (метод подключается внутри класса try...catch)
protected function getResult()
{
// если нет валидного кеша, получаем данные из БД
if ($this->startResultCache()) {
// Здесь получаем необходимые данные (через GetList и др.)
// ...
// Формируем массив arResult
$this->arResult[] = [
'NAME' => 'Мой кастомный компонент',
'ITEMS' => [
1 => 'Item 1',
2 => 'Item 2',
3 => 'Item 3',
4 => 'Item 4',
]
];
// Кеш не затронет весь код ниже, он будут выполняться на каждом хите,
// здесь работаем с другим $arResult, будут доступны только те ключи массива, которые перечислены
// в вызове SetResultCacheKeys()
if (isset($this->arResult)) {
// Ключи $arResult перечисленные при вызове этого метода, будут доступны
// в component_epilog.php и ниже по коду, обратите внимание там будет другой $arResult
$this->SetResultCacheKeys(
[]
);
// Подключаем шаблон и сохраняем кеш
$this->IncludeComponentTemplate();
} else {
// Если выяснилось, что кешировать данные не требуется, прерываем кеширование
// и выдаем сообщение «Страница не найдена»
$this->AbortResultCache();
Tools::process404(Loc::getMessage('PAGE_NOT_FOUND'),true,true);
}
}
}
/**
* Тут могут быть другие методы для получения и формирование данных.
* Но лучше не плодить тут простыню и выносить логику в отдельные классы (папка lib).
*/
}
Проверим вывод всех данных и убедимся, что все подключено и работает.
Распечатаем Demo::test() из class.php и $arParams, $arResult из template.php
Структура папки
Файл ajax.php
Тут будем принимать и обрабатывать все наши ajax-запросы.
Подробно как это работает можно почитать здесь:
Здесь же будет только заготовка.
<?php
use Bitrix\Main\Engine\ActionFilter\Authentication;
use Bitrix\Main\Engine\ActionFilter\HttpMethod;
use Bitrix\Main\Engine\ActionFilter\Csrf;
use Bitrix\Main\Engine\Controller;
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true) {
die();
}
class CustomAjaxController extends Controller {
public function configureActions():array
{
return [
/**
* Пример с включенными фильтрами.
*
* Подробно тут: https://dev.1c-bitrix.ru/api_d7/bitrix/main/engine/actionfilter/index.php
*/
// Название метода без 'Action'
'test' => [
'prefilters' => [
// Проверяет аутентифицирован ли пользователь
// и блокирует выполнение действия, если проверка не прошла, установив http status 401.
// Может выполнить редирект на страницу авторизации при необходимости.
new Authentication(),
// Проверяет, по какому http методу запускается действие
new HttpMethod([
HttpMethod::METHOD_GET, // Позволяем GET
HttpMethod::METHOD_POST // Позволяем POST
]),
// Проверяет наличие и корректность csrf-токена
new Csrf()
],
/**
* Пример с выключенными фильтрами.
*
* Чтобы удалить фильтры из дефолтных, нужно добавить знак минус "-prefilters"
*/
/*'test' => [
'prefilters' => [],
'postfilters' => []
]*/
]
];
}
/**
* Суффикс Action обязателен.
*/
public function testAction(string $personName):array
{
if (empty($personName)) {
return [
'success' => false,
'error' => 'Тут пишем ошибку для разработчика, напр. Ошибка в методе testAction()',
'message' => 'Тут сообщение для пользователя, напр. Пожалуйста, введите имя.'
];
}
return [
'success' => true,
'message' => "Привет, $personName! Ваше имя успешно получено."
];
}
}
Файл шаблона template.php
<?php if (!defined('B_PROLOG_INCLUDED') || B_PROLOG_INCLUDED !== true) {
die();
}
/** @var array $arParams */
/** @var array $arResult */
/** @global CMain $APPLICATION */
/** @global CUser $USER */
/** @global CDatabase $DB */
/** @var CBitrixComponentTemplate $this */
/** @var string $templateName */
/** @var string $templateFile */
/** @var string $templateFolder */
/** @var string $componentPath */
/** @var CBitrixComponent $component */
/*dump('$arParams', $arParams);
dump('$arResult', $arResult);*/
?>
<div class="form-wrapper">
<h2>Простая форма с AJAX</h2>
<br>
<form id="simpleForm">
<input type="text" name="personName" placeholder="Введите ваше имя">
<button type="submit">Отправить</button>
</form>
<br>
<div id="result"></div>
</div>
Файл шаблона script.js
document.addEventListener('DOMContentLoaded', () => {
testAjax();
function testAjax() {
const form = document.getElementById('simpleForm');
const resultDiv = document.getElementById('result');
if (!form || !resultDiv) {
return;
}
form.addEventListener('submit', function (e) {
e.preventDefault();
const personName = form.querySelector('[name="personName"]').value;
BX.ajax.runComponentAction('kochnev:draft', 'test', {
mode: 'ajax',
data: {
personName: personName
},
}).then(function (response) {
// console.log(response);
if (response.data.success === true) {
resultDiv.innerHTML = response.data.message;
} else {
resultDiv.innerHTML = response.data.message;
console.error(response.data.error);
}
}, function (response) {
//сюда будут приходить все ответы, у которых status !== 'success'
console.error(response);
});
})
}
});
В шаблоне лежит форма, проверяющая работу отправки запросов. При вводе текста, получаем ответ от сервера.
