Свои компоненты в ООП

21.02.2015

Начиная с 12 версии у битрикса появилась Поддержка ООП в компонентах. Но, к сожалению, разработчики не торопятся переписывать стандартные компоненты, используя всю мощь ООП. В частности поэтому, как я уже писал ранее, я не люблю использовать стандартные компоненты. В итоге я создал класс базового компонента, и наследуя его, создаю свои компоненты для конкретных нужд. Скачать мой класс базового компонента.

Основная идея заключается в том, что бы написать в базовом классе часто используемые параметры и функции. А также переопределить основную функцию работы компонента executeComponent, разбить её на подфункции для более удобного наследования.

Код переопределенной функции executeComponent:


function executeComponent() {
    try {
	$this->setParams();
	if ($this->notCache() || $this->StartResultCache(false)){
	    CModule::IncludeModule('iblock');
	    $this->inCacheFunction();
	    if ($this->includeComponentTemplateInCache){
		$this->SetResultCacheKeys($this->arSaveInCacheKeys);
		$this->IncludeComponentTemplate();
	    } else {
		$this->EndResultCache();
	    }
	}
	$this->lastCacheFunction();
	if (!$this->includeComponentTemplateInCache){
	    $this->IncludeComponentTemplate();
	}
    } catch (Exception $exc) {
	if ($this->set404){
	    @define("ERROR_404","Y");
	} elseif($this->showError) {
	    $this->__showError($exc->getMessage());
	}
	$this->AbortResultCache();
    }
}

try catch

Код обернут в try catch, для удобной обработки ошибок. Теперь, если в компоненте произошла ошибка, можно просто выкинуть исключение, например:


    throw new Exception('Елемент не найден');

Далее обработка будет зависеть от переменных $this->set404 и $this->showError, они задаются в базовом классе, и по умолчанию равны false. Или покажем страницу 404, или отобразим текст ошибки, или просто прервем работу компонента.

setParams()

Функция setParams() предназначена для дальнейшего переопределения. В ней предполагается проверка параметров компонента, установка параметров по умолчанию.

notCache()

Здесь можно определить условия когда не нужно кешировать компонент. По умолчанию функция возвращает false, т.е. кеширование будет всегда.

inCacheFunction()

Эта основная рабочая функция, которую нужно переопределять в наследуемом компоненте, и реализовывать в ней функционал компонента.

includeComponentTemplateInCache

Это флаг определяющий где будет подключаться шаблон компонента. По умолчанию значение true, что означает подключать шаблон компонента внутри кеша (результат будет закеширован). Такое поведение подходит для большинства случаев. Но бывает, что шаблон нужно подключать вне кеша, а кешировать только $arResult, тогда флаг нужно выставить в false.

$this->SetResultCacheKeys($this->arSaveInCacheKeys);

Здесь происходит сохранение в кеше некоторых ключей результирующего массива $arResult, по умолчанию это META,CHAIN, для заполнение мета тегов и цепочки хлебных крошек.

lastCacheFunction();

Функция, которая будет выполнятся всегда, не зависимо от того закеширован компонент или нет. По умолчанию здесь происходит заполнение мета тегов и цепочки хлебных крошек. Для того чтобы заполнились мета теги, в массиве $arResult должно быть следующее:


$this->arResult['META'] = array(
    'H1' => 'Это заголовок страницы',
    'DESCRIPTION' => 'Описание',
    'KEYWORDS' => 'Ключевые слова',
    'TITLE' => 'Заголовок окна браузера',
);

Для того чтобы заполнилась цепочка навигации:


$this->arResult['CHAIN'][] = array(
    'NAME' => 'Название',
    'LINK' => 'Ссылка',
);

Вспомогательные функции для наследуемых компонентов

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

getNavChainBySectionId($sectionId)

Функция по id раздела инфоблока добавит в $this->arResult['CHAIN'] всю цепочку его подразделов.

getArElements($arOrder, $arFilter, $arSelect, $getProp=false, $arNavStartParams = false, &$navString = false, $arGroupBy=false )

Функция вернет массив элементов инфоблока, согласно параметрам. Причем также вернет строку постраничной навигации если нужно, а заодно осуществит проверку, на наличие запрашиваемой страницы. Апи битрикса, если запрашивается несуществующая страница постранички, вернет результат как для первой страницы.

getArSections($arOrder, $arFilter, $arSelect, $arNavStartParams = false,$bIncCnt = false))

Функция вернет массив разделов инфоблока, согласно параметрам.

Пример создания компонента

Создадим компонент, который вернет все активные элементы инфоблока с разбивкой на страницы:


class CComponentName extends TBaseComponent {
    
    protected $showError = true;
    
    function setParams() {
        parent::setParams();
        $this->arParams['countOnPage'] = intval($this->arParams['countOnPage']);
        $this->arParams['PAGEN_1'] = intval($this->arParams['PAGEN_1']);
	if (!$this->arParams['PAGEN_1']){
	    $this->arParams['PAGEN_1'] = 1;
	}
	$this->arParams['iblockId'] = intval($this->arParams['iblockId']);
	if (!$this->arParams['countOnPage'] || !$this->arParams['PAGEN_1'] || !$this->arParams['iblockId']){
	    throw new Exception('Параметры компонента заданы неверно');
	}
    }
    
    function inCacheFunction(){
        $arFilter = array(	
            'IBLOCK_ID' => $this->arParams['iblockId'],
            'ACTIVE' => 'Y',
        );
	$arNavStartParams = array(
	    'iNumPage' => $this->arParams['PAGEN_1'],
	    'nPageSize' => $this->arParams['countOnPage'], 
	);
        $this->arResult['nawString'] = '.default';
        $this->arResult['elements'] = $this->getArElements(
                $this->arParams['elementSort'], 
                $arFilter, 
                $this->elementArSelect, 
                $this->arParams['withProp'], 
                $arNavStartParams, 
                $this->arResult['nawString']
        );
    }
}

Компонент занял 38 строчек кода. Если бы мы использовали стандартный компонент для аналогичной задачи, то остановились бы на компоненте news.list, а он занимает 422 строчки кода. Я не спорю он более универсальный, но его сложнее настраивать и гораздо сложнее кастомизировать.

PS Вот бы разработчики битрикс использовали аналогичный подход к разработки компонентов.... Ну может когда нибудь... Во всяком случае некоторое движение в эту сторону уже началось, и это не может не радовать.

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

Ученик

04.12.2015 10:05:34

Здравствуйте. Спасибо за статью. Пишете побольше про «такое»….
Я так понимаю базовый класс необходимо поместить либо в init.php либо в своем модуле?

Максим

04.12.2015 16:24:17

Я делаю так:
У меня накопились классы/функции под различные задачи, они хранятся в файлах-библиотеках. Нужные файлы я копирую в php_inerface/lib/, и в init.php подключаю (include).

А в самом init.php храню код необходимый конкретному проекту, который не получится использовать в других проектах.

Крокодил

25.10.2016 16:20:50

Вам наверняка пригодятся Базовые Битрикс Компоненты
http://bbc.bitrix.expert/
Они бесплатны и опенсорсны, их можно дорабатывать вместе с сообществом :)

Оставить комментарий:

Представьтесь пожалуйста:
Электронная почта:
Электронный адрес не публикуются
Текст сообщения:
Для подсветки кода, оборачивайте ваш код в теги <code></code>
Введите 5 цифр с картинки:

Рекомендую:

Поделюсь промокодами для хостинга TimeWeb!

Поддержать проект: