10 декабря 2017

Урок 9. Создание собственного компонента слайдера для интернет-магазина на Битрикс на CMS-Foundation

Приветствую моих читателей! Мы продолжаем строить наш собственный интернет-магазин на Битрикс редакции Старт. В прошлых уроках мы уже реализовали адаптивный каталог товаров и сделали карточку товара. Теперь пришло время немного подкрасить наш магазин и внести такую модную штуку, как слайдер. Если бы мы не пользовались никаким CSS-фреймворками, то нам потребовалось бы изучать Java Script и JQuery. Или по крайней мере искать в интернете готовые скрипты и как-то их прикручивать к сайту. Но как вы помните наш интернет магазин строится полностью на CSS-фреймворке Foundation, а в нём уже есть готовый класс для слайдера Orbit.

Но внедрять PHP код и API Битрикс непосредственно в шаблон не очень правильное решение, не bitrix-way, так сказать. Поэтому для вывода слайдера мы создадим собственный компонент. Ну и конечно при этом научимся создавать свои собственные компоненты Битрикс.

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

Логику работы мы заложим следующую. Слайдер будет строится на том же инфоблоке Товары, что и каталог. Но попадать в слайдер будут только те товары, у которых задано свойство Слайдер (SLIDER). Входными параметрами для нашего компонента будет Тип инфоблока, Инфоблок и свойство указывающее, что необходимо выводить слайдер.

Если у вас нет свойства Слайдер в инфоблоке добавьте его.

Свойство слайдер инфоблока

Тип у свойство должен быть список.


Настройка свойств инфоблока

Программно конечно со списками сложнее работать, чем со строкой или числом, зато удобнее указывать при редактировании карточки товара.

Установка свойства в инфоблоке

Инфоблок настроили, теперь можно приступить к созданию собственного компонента Битрикс. Что может быть интереснее написания собственных компонент?...

Создание компонента Битрикс

В Битрикс существует понятие пространство имен. Все стандартные компоненты Битрикс находятся в пространстве имен Bitrix в папочке /bitrix/components/bitrix/. Свои компоненты нужно располагать в своем пространстве имен, т.е. в папочке /bitrix/components/my/ или ещё лучше в папке /local/components/my/. my - это наше пространство имен.
В своем примере я буду располагать компоненты в пространстве имен startshop по пути /local/components/startshop/. Компонент так и назову slider.
Минимальная структура файлов компонента должна быть следующая:
  • component.php  - основной фал компонента, реализация логики работы компонента на API Bitrix.
    .description.php - файл описания компонента.
  • .parameters.php - файл параметров компонента.
  • templates/.default/template.php - файл шаблона по умолчанию для компонента.
Подробнее ко компонентах Битрикс можно почитать в учебном курсе для разработчиков.

Содержание этих файлов у нас будет следующим:
.description.php
<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();

$arComponentDescription = array(
    "NAME" => "Слайдер",
    "DESCRIPTION" => "Слайдер на фреймворке CSS Foundation",
    "ICON" => "/images/icon.gif",
    "SORT" => 100,
    "CACHE_PATH" => "Y",
    "PATH" => array(
            "ID" => "startshop",
            "NAME" => 'Компоненты StartShop'
            ),
);
?>


В этом фале задается наименование и описание компонента. А так же иконка для отображения в палитре компонентов и параметр PATH указывает на то, в какой папочке будет находится компонент в палитре компонентов.

Собственный компонент Битрикс



.parameters.php
<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true) die();

if(!CModule::IncludeModule("iblock"))
    return;

$arTypesEx = CIBlockParameters::GetIBlockTypes(array("-"=>" "));

$arIBlocks=array();
$db_iblock = CIBlock::GetList(array("SORT"=>"ASC"), array("TYPE" => ($arCurrentValues["IBLOCK_TYPE"]!="-"?$arCurrentValues["IBLOCK_TYPE"]:"")));
while($arRes = $db_iblock->Fetch())
    $arIBlocks[$arRes["ID"]] = "[".$arRes["ID"]."] ".$arRes["NAME"];

$arProperty_LNS = array();
$rsProp = CIBlockProperty::GetList(array("sort"=>"asc", "name"=>"asc"), array("ACTIVE"=>"Y", "IBLOCK_ID"=>($arCurrentValues["IBLOCK_ID"])));
while ($arr=$rsProp->Fetch())
{
    $arProperty[$arr["CODE"]] = "[".$arr["CODE"]."] ".$arr["NAME"];
    if (in_array($arr["PROPERTY_TYPE"], array("L", "N", "S")))
    {
        $arProperty_LNS[$arr["CODE"]] = "[".$arr["CODE"]."] ".$arr["NAME"];
    }
}

$arComponentParameters = array(
    "PARAMETERS" => array(
        "IBLOCK_TYPE" => array(
            "PARENT" => "BASE",
            "NAME" => "Тип инфоблока",
            "TYPE" => "LIST",
            "VALUES" => $arTypesEx,
            "DEFAULT" => "news",
            "REFRESH" => "Y",
        ),
        "IBLOCK_ID" => array(
            "PARENT" => "BASE",
            "NAME" => "Инфобок",
            "TYPE" => "LIST",
            "VALUES" => $arIBlocks,
            "DEFAULT" => '={$_REQUEST["ID"]}',
            "ADDITIONAL_VALUES" => "Y",
            "REFRESH" => "Y",
        ),
        "PROPERTY_CODE" => array(
            "PARENT" => "DATA_SOURCE",
            "NAME" => "Укажите свойство по которому будет фильтроваться товары для слайдера",
            "TYPE" => "LIST",
            "MULTIPLE" => "N",
            "VALUES" => $arProperty_LNS,
            "ADDITIONAL_VALUES" => "Y",
        ),
    ),
);


В файле параметров все намного сложнее. Но если вы уже немного владеете API Битрикс, то можно понять, что верхний код на API Битрикс получает три массива:
  1. $arTypesEx - массив с типами доступных инфоблоков.
  2. $arIBlocks - массив со списком инфоблоков отфильтрованному по данному типу.
  3. $arProperty_LNS - массив всех свойств выбранного инфоблока.
Совсем уж подробно я не буду описывать, очень долго выйдет. Скажу только, что данный код запоминать и самому писать совсем не нужно, я сам его взял из типового компонента bitrix:news.list. Убрал лишнее и получил нужный мне файл параметров.

Параметры Слайдера

Вот такие параметры будут доступны в настройках нашего компонента из публичной части сайта.

component.php
<?
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
use Bitrix\Main\Loader;
    
if(!Loader::includeModule("iblock"))
{
    return;
}

$arSelect = Array("ID", "NAME", "PREVIEW_PICTURE", "DETAIL_PAGE_URL", "PROPERTY_".$arParams["PROPERTY_CODE"]);
$arFilter = Array("IBLOCK_ID" => IntVal($arParams["IBLOCK_ID"]), "ACTIVE"=>"Y", "PROPERTY_".$arParams["PROPERTY_CODE"]."_VALUE" => 'Да');
$res = CIBlockElement::GetList(Array(), $arFilter, false, false, $arSelect);
while($arFields = $res->GetNext())
{
    $arResult[] = $arFields;    
}

$this->includeComponentTemplate();
?>


Код компонента получился очень короткий в отличие от стандартного кода вывода списка новостей. Тут нет ничего лишнего. Вначале мы объявили пространство имен для загрузчика Loader, далее с его помощью подгрузили модуль инфоблоков iblock. И с помощью самой распространенной конструкции API Bitrix CIBlockElement::GetList() выполнили запрос к базе данных отобрав записи инфоблока Товары, в котором свойство Слайдер установлено в занчение "Да". Далее результатом выборки заполнили предопределенный массив $arResult и последней строкой подключили файл шаблона.

templates/.default/template.php
<?
if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();
?>

<div class="orbit" role="region" aria-label="Favorite Space Pictures" data-orbit>
    <div class="orbit-wrapper">
        <div class="orbit-controls">
            <button class="orbit-previous"><span class="show-for-sr">Предыдущий</span>&#9664;&#xFE0E;</button>
            <button class="orbit-next"><span class="show-for-sr">Следующий</span>&#9654;&#xFE0E;</button>
        </div>
        <ul class="orbit-container">

        <?foreach ($arResult as $item): ?>

            <?
                $file = CFile::ResizeImageGet($item["PREVIEW_PICTURE"], array('width' => 1100,'height' => 500), BX_RESIZE_IMAGE_EXACT, true);
            ?>

            <li class="orbit-slide">
                <figure class="orbit-figure">
                    <img class="orbit-image" src="<?=$file['src']?>" alt="Space">
                    <figcaption class="orbit-caption"><?=$item['NAME']?></figcaption>
                </figure>
            </li>

        <?endforeach;?>

        </ul>
    </div>

    <nav class="orbit-bullets">

        <?foreach ($arResult as $item=>$key): ?>
            <button data-slide="<?=$key?>"><span class="show-for-sr"><?=$item['NAME']?></span></button>
        <?endforeach;?>

    </nav>
</div>


Шаблон даже получился более громоздкий, чем компонент. Но если посмотрите тут все просто. Код верстки слайдера взять целиком из CSS-фреймворка Foundation. Далее я уже приводил принцип работы с массивом $arResult в уроке когда мы выводили каталог товаров. Делаем выполняем цикл по массиву и выводим нужные нам значения. Тут пришлось правда два цикла сделать - не очень оптимально, но это не обращение к базе данных и цикл по массиву из 3-5 записей не нагрузит ваш сайт. По этому усложнять код и избегать второго цикла я счел не нужным.
Строкой $file = CFile::ResizeImageGet($item["PREVIEW_PICTURE"], array('width' => 1100,'height' => 500), BX_RESIZE_IMAGE_EXACT, true); я снова подгоняю картинки под требуемый размер. Подробнее все в том же уроке про вывод каталога.
Вот что в итоге получилось.

Наш Слайдер


Тут конечно надо заметить, что не очень красиво получилось. По хорошему нужно подобрать пропорциональные картинки и разместить их в отдельном инфоблоке. Вы попробуйте так и сделать, код компонента при этом обсалютно не изменится, даже упростится, не потребуется условие отбора по свойству Слайдер. Вобщем пример при этом не страдает, по этому переделывать я не стану, а лучше напишу побыстрее следующий урок.
И как всегда выкладываю исходный код урока:
компонент slider
шаблон этого урока

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


Комментарии

Подписаться на комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
13
14.06.2018 | Антон

Почему же не работать с визуальной частью сайта (в частности с картинками) средствами CSS?? Зачем городить php для картинок и в предыдущих уроках сетку под разные экраны?? Ведь для этого верстка на CSS Foundation! Эх)

Комментировать
Подписаться на комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
13
Закрыть
14.06.2018 | Администратор

А как средствами CSS можно смасштабировать картинку, которая изначально не подходящего размера и не потерять пропорции?

Комментировать
Подписаться на комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
13
Закрыть
14.06.2018 | Антон

Например так img { max-width:100%; height:auto; }

Комментировать
Подписаться на комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
13
Закрыть
15.06.2018 | Администратор

Как вариант да, но если изображении сильно не пропорциональное оно уменьшится. А в случае обработки через CFile::ResizeImageGet() обрезается. Вобщем чтобы иметь качественный каталог, нужно изначально хорошие пропорциональные изображения. Я на это время не тратил.

Комментировать
Подписаться на комментарии
Защита от автоматических сообщений
CAPTCHA
Введите слово на картинке
13
Закрыть


Возврат к списку