Предисловие Сижу я такой, делаю интернет-магазин. И уже второй клиент просит меня поставить компонент для управления выводом товаров по персональным рекомендациям (BigData). Я не любитель применять новые фишки битрикс пока не услышу что "это" уже не сырое и можно использовать. Ну, думаю я , срок уже подошёл, к тому же вроде как всё само должно работать. А нет (не должно было удивить), само всё работать будет только для магазина из коробки (Современный интернет магазин от битрикс).
Разочарование Открываю я компонент catalog.bigdata.products и вижу о ужас, тот же самый фарш что в новых компонентах для магазина после версии 12.0. Очень много кода, код тянется давно и разбираться в нём нет никакого желания: там и корзина и пересчёты и ску. Что делать если в простом магазине всего этого нет, а добавление товара в корзину происходит всего 1 строчкой? Что делать тем, кто не использует весь "фарш" универсальных компонентов - а просто пишет только то, что необходимо, и не оставляет кучу хвостов в своём коде? Открыв этот шаблон и ковыряя его, я всё проклял) и написал жалобное сообщение здесь. На что получил интересный ответ, который помог написать свой компонент для "упрощённой работы".
Принцип работы компонента catalog.bigdata.products Компонент большой, наследуется от catalog.viewed.products, тащит за собой много чего. Тонны тонны кода в шаблоне. Идея работы:
Компонент отрабатывает первый раз - делает запрос к сервису (в облако) (только запрос)
Компонент отрабатывает второй раз посылает запрос к аякс странице (уже в компоненте) (подставляя значения полученные из облака)
Отображает данные (подгружает аякс), вешает события и т.д. (Схема очень упрощенная так как есть много всяких разных ньюансов)
Как же работает персонализация? В нужный момент (переход по ссылке или бросок в корзину) происходит установка специальных куков (в которых указан ID товара, рекомендация и время). К тому же компонент catalog.element генерирует какой-то js код, при оформлении заказа видимо куки улетают на сервис и там происходит всякая магия.
Ближе к делу (к коду) Я решил написать свой собственный компонент который выполняет минимальные операции по работе с персонализацией. идея у меня останется прежней, а вот кода будет меньше.
RCM_TYPE - полностью слизан с catalog.viewed.products (то есть весь тот же самый список рекомендаций) ELEMENT_ID/ELEMENT_CODE - это ID/код товара, к которому будут подбираться "похожие товары" по рекомендации ELEMENTS_LIMIT - Количество ID элементов для запроса в облако Остальные параметры интуитивно понятны
Метод в компоненте, который устанавливает массив для запроса в облако:
public function setBigData($type = null, $productId = null)
{
$this->dataToRequest = array(
'uid' => $_COOKIE['BX_USER_ID'], //Кука пользователя
'aid' => Counter::getAccountId(), // хэш лицензии (\Bitrix\Main\Analytics\Counter)
'count' => $this->arParams['ELEMENTS_LIMIT'], //количество
);
//Id товара, если нужно искать похожие
$productId = intval($productId);
if ($productId)
$this->productId = $productId;
if ($type)
$this->setType($type); //выбор рекомендации
}
Метод для выбора рекомендации (слизан с catalog.bigdata.products) ничего сложного просто дополнение уже установленного массива данными в зависимости от рекомендации:
На этом основные методы компонента можно опустить (больше ничего и не требуется, но я написал ещё метод curl если кому то будет необходимо)
Шаблон нашего компонента
<?if(!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED!==true)die();?>
<div class="bigdata-recommended"> <!--Блок родитель-->
<div class="bigdata-wrap"></div> <!--Блок куда будут вставляться данные ajax запросом-->
</div>
<sc ript>
var bigData = { // объект хранилище для запросов
'cookie_prefix': '<?=CUtil::JSEscape(COption::GetOptionString("main", "cookie_name", "BITRIX_SM"))?>', //префикс
'cookie_domain': '<?=$APPLICATION->GetCookieDomain()?>', //домен
'recommendationId': '<?=$arResult['RID']?>', //ID рекомендации, установленной в компоненте
'ajaxElementsPage': '<?=$componentPath?>/ajax.php', // страница с кодом, который будет выполнятся после запроса в облако
'data': <?=CUtil::PhpToJSObject($arResult['BIG_DATA'])?>, //данные для запроса
'url': '<?=$arResult['REQUEST_URL']?>', //url для запроса
'detailPageUrlRecommendedClass': 'bx_rcm_view_link', //класс, который нужно проставить для ссылок, ведущих на детальную карточку товара (ВАЖНО!)
'addToCartActionClass': 'add2cart' //класс, который нужно проставить для тега корзины (ВАЖНО!)
}
</sc ript>
С помощью двух последний параметров идёт установка кук, которые необходимы для работы с персонализацией.
Файл script.js
function getCookie(name) {
// Опущу описание, так как это просто функция, которая возвращает значение куки по заданному имени
}
function rememberRecommend(rcmId, productId){ //слизано с catalog.bigdata.products, теперь можно сразу указать тип рекомендации и ID товара. В стандартном компоненте подавался ещё и объект, нам не нужно
var plCookieName = bigData.cookie_prefix + '_RCM_PRODUCT_LOG';
var plCookie = getCookie(plCookieName);
var itemFound = false;
var current_server_time = new Date().getTime();
var cItems = [],
cItem;
if (plCookie)
{
cItems = plCookie.split('.');
}
var i = cItems.length;
while (i--)
{
cItem = cItems[i].split('-');
if (cItem[0] == productId)
{
cItem = cItems[i].split('-');
cItem[1] = rcmId;
cItem[2] = current_server_time;
cItems[i] = cItem.join('-');
itemFound = true;
}
else
{
if ((current_server_time - cItem[2]) > 3600*24*30)
{
cItems.splice(i, 1);
}
}
}
if (!itemFound)
{
cItems.push([productId, rcmId, current_server_time].join('-'));
}
var plNewCookie = cItems.join('.');
var cookieDate = new Date(new Date().getTime() + 1000*3600*24*365*10);
document.cookie=plCookieName+"="+plNewCookie+"; path=/; expires="+cookieDate.toUTCString()+"; domain="+bigData.cookie_domain; //Установка куки
}
//Получение кода (html) со странице, которая будет вызвана после запроса в облако (возвращаемые данные вставляются в контейнер).
function getProducts(ids){
console.log('Getting ajax page...');
$.ajax({
url : bigData.ajaxElementsPage,
data: {'IDS': ids} //Полученные ID товаров из облака
}).done(function(html) {
console.log('Ajax page is getted');
if (!html)
console.log('No items found');
$('.bigdata-recommended .bigdata-wrap').html(html);
});
}
$(document).ready(function(){
//Событие на клик ссылки для перехода на детальную страницу.
//(ВАЖНО!)Сопроводить все ссылки на детальную карточку классом из переменной bigData.detailPageUrlRecommendedClass и атрибутом data-product-id в котором лежит значение ID элемента
$(document).on('click', ".bigdata-recommended ." + bigData.detailPageUrlRecommendedClass, function(event){
event.preventDefault();
var _this = $(this);
var productId = _this.data('product-id');
rememberRecommend(bigData.recommendationId, productId);
location.href = _this.attr('href');
});
//Событие на клик добавления в корзину.
//(ВАЖНО!)Сопроводить тег с добавлением в корзину классом из переменной bigData.addaddToCartActionClass и атрибутом data-product-id
$(document).on('click',".bigdata-recommended ." + bigData.addaddToCartActionClass, function(e){
e.preventDefault();
var _this = $(this);
var productId = _this.data('product-id');
rememberRecommend(bigData.recommendationId, productId);
});
console.log('Getting ids...');
// Запрос к облаку BigData
$.ajax({
method : "POST",
url : bigData.url,
data: bigData.data
}).done(function(response) {
response = JSON.parse(response);
if (!response.items)
return;
console.log('Ids is getted');
getProducts(response.items);
});
});
В принципе всё! Единственное в чём я сомневаюсь это какой RID (recomenadion ID) должен передаваться в облако, потому что в стандартном компоненте, он то принимает значение из списка, то какой-то хеш, если кто-то знает, буду рад совету.
Спасибо Медведеву Дмитрию, за наводку (привет битрикс), Сухареву Антону из "Кузницы" за "поделился идеей работы bigdata"
ЗЫ: Для битрикса remember пишется с одной M. ЗЫ2: Я чувствую что не настанет того дня когда CMS будет писаться и для разработчиков в том числе. А это плохо, плохо ковырять продакшн код не имея документации и не имея примеров использования - отсюда все проблемы. 9 проектов из 10 используют стандартные компоненты, а использование кода в этих компонентах под задачи стремится к 1% (про шаблоны идёт речь). И никакие композиты, оптимизации и аналитики или хостинги не решат этих проблем. Битрикс становится прожорливее и не успевает железо за его ненасытными потребностями или потребностями менеджеров.
Когда Тейлора (создателя фреймворка Laravel) спросили: «Стоило ли так много времени тратить на документирование?», он ответил, что лучше задержит релиз Laravel 5.1, чем выпустит его с плохой документацией.
Александр Аваков, Сталкивался, но так и не выявил причину, так как происходило это через раз или через несколько раз. У меня такая гипотеза, что данных в облаке ещё нет, поэтому ничего не приходит (а в стандартном битрикс компоненте в таком случае подключаются самые просматриваемые товары). Но это не единственная проблема биг даты от битрикса, на данный момент нет ни одного клиента кто был бы доволен этим "виджетом" или попросил его оставить. Если есть ответ и он пустой - значит что данные прошли и пришёл ответ - вероятнее всего никакой, ну нету по данным параметрам рекомендуемых товаров:) Попробуйте изменить тип, например без персонализации
Евгений Микулич, в итоге, с клиентом договорились проработать дополнительную логику, если от серверов битрикса пришел пустой ответ. Мы выбираем содержимое ближайшей категории, и выводим как рекомендации к текущему товару. Просто вокруг этой бигдаты было столько плясок, восхищений и оров. Я на нее надеялся как на простой способ не заполнять кучу рекомендованных товаров как свойство.
Александр Аваков, Проблема в том, что пощупать и проверить нельзя - это черная коробка. Проверить как и что работает невозможно, данные обнулить невозможно. Можно только запросы тыкать, повезёт или нет) Из моего круга знакомых её никто не использует вообще
Александр Аваков, Вот простой пример. У меня есть каталог. Он в биг дате. Теперь я часть ассортимента из каталога удалил, ну нету больше такого товара - не торгую я им. В биг дату я посылаю запрос на 10 рекомендованных товаров, возвращается 10 ИД товаров и все из них в базе уже не существуют, или часть уже не существует. Что делать?) Ждать когда пройдёт 2 недели и данные обновятся?
Подскажите, а заказы у вас отмечаются при этом как персонализированные или как такое доделать можно? День бьюсь, через стнадратный компонент персонализированные товары, через кастомный - нет, как обычный заказ с обычными товарами.
Старикевич Максим, Нужно чтобы была включена персонализация, и установлена кука специальная, эта кука проверяется при покупке. Делал давно, сейчас не помню как
Старикевич Максим, если вы сами товар добавляете в корзину, то в функциях Add2Basket или Add2BasketByProductID надо в массиве arProductParams кроме всего передать "секретное" свойство "RECOMMENDATION" => 1, и тогда товар и сам заказ отметится голубой иконкой рекомендаций.
Про пользу документации - поддерживаю полностью. Про возможность через наследование добавить функционал, не ломая непонятные потроха вокруг - поддерживаю.
Группы на сайте создаются не только сотрудниками «1С-Битрикс», но и партнерами компании. Поэтому мнения участников групп могут не совпадать с позицией компании «1С-Битрикс».