1С-Битрикс. Расширяем CCatalogProductProvider для кастомного DETAIL_PAGE_URL и NAME у товара
До версии 12.5 можно было просто подменять урл товаров, которые добавляются в корзину.
Нужно это было, например для того, чтобы переходя из корзины в карточку товара, подсвечивать выбранную характеристику.
В более старших версиях добавили новое поле в корзину PRODUCT_PROVIDER_CLASS, которое теперь берет на себя взаимодействие торгового каталога и интернет-магазина. По умолчанию это CCatalogProductProvider.
Если теперь мы добавим товар в корзину таким образом:
$arFields = array( 'PRODUCT_ID' => 1, 'NAME' => 'Новое имя товара', 'PRICE' => 100, 'DETAIL_PAGE_URL' => '/custom_url/', ); CSaleBasket::Add($arFields);
Зайдем в корзину, и с удивлением обнаружим, что у добавленного товара «Название» и «Страница детального просмотра» поменялись на те, которые настоящие у товара, а не то что мы передали функции CSaleBasket::Add.
Всему виной провайдер CCatalogProductProvider, который и поддерживает взаимодействие с интернет магазином. Этот класс использует интерфейс IBXSaleProductProvider. Если заглянуть в код класса, то можно увидеть следующее:
$arResult = array( "NAME" => $arProduct["~NAME"], "CAN_BUY" => "Y", "DETAIL_PAGE_URL" => $arProduct['~DETAIL_PAGE_URL'], "BARCODE_MULTI" => $arCatalogProduct["BARCODE_MULTI"], "WEIGHT" => intval($arCatalogProduct['WEIGHT']), "DIMENSIONS" => serialize(array( "WIDTH" => $arCatalogProduct["WIDTH"], "HEIGHT" => $arCatalogProduct["HEIGHT"], "LENGTH" => $arCatalogProduct["LENGTH"] ) ), "TYPE" => ($arCatalogProduct["TYPE"] == CCatalogProduct::TYPE_SET) ? CCatalogProductSet::TYPE_SET : NULL ); return $arResult;
Тут то и происходит подмена наших полей на стандартные.
Чтобы решить эту проблему, мы создадим свой провайдер, назовем его CCatalogProductProviderCustom, и подключим его в init.php
Код его будет такой:
if (!CModule::IncludeModule("sale") || !CModule::IncludeModule("catalog")) return false; IncludeModuleLangFile(__FILE__); class CCatalogProductProviderCustom extends CCatalogProductProvider { public static function GetProductData($arParams) { // code } public static function OrderProduct($arParams) { // code } }
Код функций GetProductData и OrderProduct надо взять из исходного класса CCatalogProductProvider. Только убрав в них две злосчастные строчки, чтобы получилось примерно так:
$arResult = array( //"NAME" => $arProduct["~NAME"], "CAN_BUY" => "Y", //"DETAIL_PAGE_URL" => $arProduct['~DETAIL_PAGE_URL'], "BARCODE_MULTI" => $arCatalogProduct["BARCODE_MULTI"], "WEIGHT" => intval($arCatalogProduct['WEIGHT']), "DIMENSIONS" => serialize(array( "WIDTH" => $arCatalogProduct["WIDTH"], "HEIGHT" => $arCatalogProduct["HEIGHT"], "LENGTH" => $arCatalogProduct["LENGTH"] ) ), "TYPE" => ($arCatalogProduct["TYPE"] == CCatalogProduct::TYPE_SET) ? CCatalogProductSet::TYPE_SET : NULL );
И теперь при добавлении товара в корзину при помощи CSaleBasket::Add надо передавать передавать PRODUCT_PROVIDER_CLASS равным CCatalogProductProviderCustom.
На этом всё. Можно использовать свои урлы и названия у товаров в корзине. Например, удобно дописывать в скобки артикул товару
8 комментариев
Здравствуйте. Вы не могли бы выложить итоговый текст файла php.ini?
Просто, вот этот кусок
необходимо, я так полагаю, во что то обернуть?
Олег, добрый вечер. Этот кусок кода нужно вставить в файл, где будет хранится ваш провайдер, например /bitrix/php_interface/providers/product_provider_custom.php
И далее подключить этот файл в init.php
Добрый день. У меня при создании заказа, в админку падают товары и все бы хорошо, но при редактировании заказа, товары которые были со скидкой, почему-то слетает скидка, именно после нажатия на кнопку, изменить заказ. Тех поддержка мне написали, что "У вас при добавлении товара в корзину не прописан PRODUCT_PROVIDER_CLASS, он должен быть равен "CCatalogProductProvider". Поэтому и не распространяется скидка. " Как быть, что сделать чтобы при оформлении заказа, значение записывалось такое как они пишут !
Можно не переписывать метод класса родителя GetProductData. Можно использовать: $arParent = parent::GetProductData($arFields); а потом уже менять массив :)
Виталий, конечно! Даже нужно, я бы сказал. Заметка не нова — перепишу на досуге.
Олег, здравствуйте! Не много не по теме, но пытаюсь решить одну задачу - смену типа цены по купону в корзине. Никак не соображу, как лучше это сделать. Через эти обратные функции?
Роман, как вариант — да
Олег, сделал через хендлеры к событиям корзины.