Сортировать товары по названию, цене и свойствам в каталоге 1С-Битрикс

Просмотров: 6087

Задача: реализовать возможность сортировки товаров в разделах каталога. Сортировка должна работать с использованием AJAX. В качестве параметров сортировки используются: по алфавиту, по цене, по новизне, просмотрам и по брендам.

Сортировать товары по названию, цене и свойствам в каталоге 1С-Битрикс

В файле section.php комплексного шаблона каталога, до вывода bitrix:catalog.section добавляем:

<form class="sortline" method="post" action="/local/ajax/sort.php">
  Сортировать по:
  <select name="sortten">
    <option value="show_counter"<? echo $_COOKIE['sortten'] === 'show_counter' ? ' selected' : ' '; ?>>
      Просмотрам
    </option>
    <option value="name"<? echo $_COOKIE['sortten'] === 'name' ? ' selected' : ' '; ?>>
      Алфавиту
    </option>
    <option value="SCALED_PRICE_2"<? echo $_COOKIE['sortten'] === 'SCALED_PRICE_2' ? ' selected' : ' '; ?>>
      Цене
    </option>
    <option value="property_BRANDS_REF"<? echo $_COOKIE['sortten'] === 'property_BRANDS_REF' ? ' selected' : ' '; ?>>
      Производителям
    </option>
  </select>
</form>

Этот код отображает форму с элементом select для выбора способа сортировки элементов на странице. Форма отправляется методом POST на адрес /local/ajax/sort.php, когда пользователь выбирает один из вариантов сортировки.

Атрибут name элемента select имеет значение sortten, что указывает на то, что выбранный вариант сортировки будет передан на сервер с помощью POST-запроса в виде массива $_POST['sortten'].

Для каждого варианта сортировки определено свое значение атрибута value, которое соответствует выбранному пользователем варианту. Также в каждой опции используется PHP-код для проверки значения куки 'sortten', хранящей выбранный пользователем вариант сортировки. Если значение куки равно значению атрибута value текущей опции, то устанавливается атрибут selected, чтобы эта опция была выбрана по умолчанию.

Таким образом, при отправке формы методом POST на сервер будет передано значение выбранного варианта сортировки в виде массива $_POST['sortten']. Значение куки 'sortten' будет обновлено на сервере в соответствии с выбранным пользователем вариантом сортировки.

Отправка формы с ajax, без кнопки отправки

Здесь же, в section.php или в подключаемом js файле (рекомендую), добавляем javascript код. Обратите внимаение, что в нем используется jquery - не забудте его подключить

$(".sortline").change(function (event) {
    event.preventDefault();
    var form = $(this).closest('form')[0];
    var formData = new FormData(form);
    $('body').addClass('loading_body');
    $.ajax({
        url: form.action,
        type: form.method,
        data: formData,
        processData: false,
        contentType: false,
        success: function (response) {
            location.reload();
        },
        error: function () {
            console.log("Произошла ошибка при отправке запроса.");
        }
    });
});

Этот код реализует функцию, которая выполняется при изменении элемента с классом "sortline". Когда происходит изменение, функция отправляет AJAX-запрос на сервер с данными из формы, содержащей элемент с классом "sortline".

Затем данные формы обрабатываются объектом FormData, который позволяет удобно собирать данные формы и отправлять их в виде multipart/form-data.

После этого происходит отправка AJAX-запроса с помощью функции $.ajax(), где указывается адрес url и метод type запроса, а также данные formData.

Если запрос успешен, то функция обновляет обновляет страницу в текщем уровне прокрутки. На время отправки запроса для элемента body добавляется class 'loading_body', что бы можно было стилизовать его на время отправки запроса.

Запись в COOKIE данных из формы

В деректории "/local/ajax/" создаем файл sort.php c содержимым:

function process_form_data($data) {
    // Обработка данных формы
    if (empty($data['sortten'])) {
        return false;
    }
    return $data['sortten'];
}

function set_cookie($name, $value, $expire = 0) {
    // Установка куки
    setcookie($name, $value, $expire, '/', '', false, true);
}

// Обработка данных формы
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $sortten = process_form_data($_POST);
    if ($sortten !== false) {
        set_cookie('sortten', $sortten);
    }
}

Этот код выполняет следующие действия:

  • Определяется функция process_form_data, которая принимает данные формы в качестве аргумента $data.
  • Функция проверяет, содержит ли массив $data ключ 'sortten', и если нет, то возвращает false.
  • Если ключ 'sortten' присутствует в массиве $data, то функция возвращает его значение.
  • Определяется функция set_cookie, которая принимает имя куки $name, значение $value и необязательный срок истечения действия куки $expire.
  • Функция set_cookie вызывает функцию setcookie() для установки куки с заданным именем, значением и сроком истечения.

Если метод запроса на сервер является POST ($_SERVER['REQUEST_METHOD'] === 'POST'), то выполняется следующее:

  • вызывается функция process_form_data с массивом данных формы $_POST в качестве аргумента;
  • если функция process_form_data возвращает не false, то вызывается функция set_cookie для установки куки с именем 'sortten' и значением, возвращенным функцией process_form_data.

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


    <?
    if (count($_COOKIE['sortten']) > '0') {
        $sort = $_COOKIE['sortten'];
    } else {
        $sort = $arParams["ELEMENT_SORT_FIELD"];
    }
    $intSectionID = $APPLICATION->IncludeComponent(
        "bitrix:catalog.section",
        "section",
        array(
            //... сокращен catalog.section
            "ELEMENT_SORT_FIELD" => $sort,
            "ELEMENT_SORT_ORDER" => ($_COOKIE['sortten'] === 'show_counter') ? 'desc' : 'asc',
            //... сокращен catalog.section
        ),
        $component
    );
    ?>

Если сортировка еще не выбиралась, значит в COOKIE нет ключа ['sortten'], тогда используем сортировку из настроек компонента. Если ключ есть, используем параметр сортировки из него.

Обратите внимение: направление для сортировки по просмотрам перевернуто ("по убыванию"), так что бы более просматриваемые товары были в начале. Для остальных сортировок используется параметр "по возрастанию"

Вариант сортировки с кнопками вместо select

Вы можете переделать эту форму, заменив элемент select на набор кнопок button. Вот как это можно сделать, меняем форму:

<form class="sortline" method="post" action="/local/ajax/sort.php">
    <span>Сортировать по:</span>
    <input type="hidden" name="sortten" value="<?php echo $_COOKIE['sortten']; ?>">
    <button type="submit" name="sortten" value="show_counter" <?php echo $_COOKIE['sortten'] === 'show_counter' ? 'class="selected"' : ''; ?>>
        Популярности
    </button>
    <button type="submit" name="sortten" value="name" <?php echo $_COOKIE['sortten'] === 'name' ? 'class="selected"' : ''; ?>>
        Алфавиту
    </button>
    <button type="submit" name="sortten" value="SCALED_PRICE_1" <?php echo $_COOKIE['sortten'] === 'SCALED_PRICE_2' ? 'class="selected"' : ''; ?>>
        Цене
    </button>
</form>

Здесь я заменил select на набор кнопок button. У каждой кнопки есть type="submit", чтобы они отправляли форму при нажатии. Также я добавил скрытое поле input type="hidden", чтобы передавать значение выбранной сортировки, как и в исходном коде с помощью select. Каждая кнопка имеет атрибут name="sortten" и разные значения value, которые будут отправлены вместе с формой в зависимости от выбора пользователя. В PHP-коде я также добавил проверку, чтобы установить класс "selected" для выбранной кнопки, чтобы она могла быть стилизована соответственно.

Чтобы обработчик и скрипт правильно работали с изменениями в форме, вам нужно внести соответствующие изменения. Ниже представлены обновленные версии скрипта и обработчика:

$(".sortline button").click(function (event) {
    event.preventDefault();
    var form = $(this).closest('form')[0];
    var formData = new FormData(form);
    formData.set('sortten', $(this).val()); // Устанавливаем значение кнопки в formData
    $('.loading_body').addClass('loading_body_show');
    $.ajax({
        url: form.action,
        type: form.method,
        data: formData,
        processData: false,
        contentType: false,
        success: function (response) {
            location.reload();
        },
        error: function () {
            console.log("Произошла ошибка при отправке запроса.");
        }
    });
});

Обработчик в sort.php:

function process_form_data($data) {
    // Обработка данных формы
    if (empty($data['sortten'])) {
        return false;
    }
    return $data['sortten'];
}

function set_cookie($name, $value, $expire = 0) {
    // Установка куки
    setcookie($name, $value, $expire, '/', '', false, true);
}

// Обработка данных формы
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $sortten = process_form_data($_POST);
    if ($sortten !== false) {
        set_cookie('sortten', $sortten);
        // Возвращаем успешный ответ
        echo json_encode(['success' => true]);
        exit;
    }
}

Обновленный скрипт jQuery теперь привязан к событию click на кнопках внутри .sortline. Когда пользователь нажимает на одну из кнопок, значение этой кнопки устанавливается в formData, затем отправляется через AJAX.

Обработчик PHP также был обновлен для учета изменений в форме. Он теперь принимает значение sortten из POST-запроса, устанавливает соответствующую куку и возвращает успешный ответ в формате JSON.

Михаил Базаров 22.04.2023
Сортировку можно произвести по стандартным полям, для чего можно воспользоваться приведенным ниже списком:

id - ID элемента;
sort - индекс сортировки;
timestamp_x - дата изменения;
name - название;
active_from или date_active_from - начало периода действия элемента;
active_to или date_active_to - окончание периода действия элемента;
status - код статуса элемента в документообороте;
code - мнемонический код элемента;
iblock_id - числовой код информационного блока;
modified_by - код последнего изменившего пользователя;
active - признак активности элемента;
show_counter - количество показов элемента (учитывается функцией CIBlockElement::CounterInc);
show_counter_start - время первого показа элемента (учитывается функцией CIBlockElement::CounterInc);
shows - усредненное количество показов (количество показов / продолжительность показа);
rand - случайный порядок;
xml_id или external_id - внешний код;
tags - теги;
created - время создания;
created_date - дата создания без учета времени;
cnt - количество элементов (только при заданной группировке)
SCALED_PRICE_<ID> - по ID типа цены
Гость 01.08.2023
А есть ли статья по сортировке категорий по алфавиту()?
Ни одной статьи и адекватного ответа не попалось...  
Михаил Базаров 01.08.2023
Если выводите разделы компонентом catalog.section.list можете передать ему параметр
CUSTOM_SECTION_SORT в котором массив из правил сортировки для метода CIBlockSection::GetList.
Что-то вроде этого:
Код
'CUSTOM_SECTION_SORT' => array (
      'NAME' => 'ASC'
)

Это есть в документации к catalog.section.list
Если что-то другое имели ввиду, нужен более развернутый вопрос.