При разработке сайтов на Битрикс, с интеграцией с 1С Управление Тороговлей, нужно запретить изменения полей при обмене. В частности, детальное описание и картинку товара.

Если вы используете 1C для выгрузки структуры каталога, цен, торговых предложений и свойств товаров на ваш сайт, а описания и картинки вы добавляете уже после выгрузки, то у вас могут возникнуть проблемы. При обмене данными, информация, добавленная на сайте, может быть перезаписана. Это происходит потому, что 1C "видит", что у товара нет описания (в своей базе), но на сайте оно присутствует, и поэтому происходит удаление этого товара.
Чтобы избежать такой ситуации, можно воспользоваться событиями OnBeforeIBlockElementUpdate и OnBeforeIBlockElementAdd. Для этого добавьте следующий код в файл /bitrix/php_interface/init.php (если файла нет, создайте его):
AddEventHandler("iblock", "OnBeforeIBlockElementUpdate","DoNotUpdate");
function DoNotUpdate(&$arFields)
{
if ($_REQUEST['mode'] == 'import') {
unset($arFields['PREVIEW_PICTURE']);
unset($arFields['DETAIL_PICTURE']);
unset($arFields['PREVIEW_TEXT']);
unset($arFields['DETAIL_TEXT']);
}
}
AddEventHandler("iblock", "OnBeforeIBlockElementAdd","DoNotAdd");
function DoNotAdd(&$arFields)
{
if ($_REQUEST['mode'] == 'import') {
unset($arFields['PREVIEW_PICTURE']);
unset($arFields['DETAIL_PICTURE']);
unset($arFields['PREVIEW_TEXT']);
unset($arFields['DETAIL_TEXT']);
}
}
В данном случае мы запретили изменение и добавление следующих полей: картинка анонса, детальная картинка, текст анонса и детальный текст. Путем добавления соответствующих строк вы можете запретить изменение любого поля товара.
Аналог на D7 для запрета изменений при обмене данными
Вы также можете использовать D7 для реализации запрета на изменение полей при обмене данными. Вот пример кода:
use Bitrix\Main\EventManager;
EventManager::getInstance()->addEventHandler(
'iblock',
'OnBeforeIBlockElementUpdate',
'DoNotUpdate'
);
EventManager::getInstance()->addEventHandler(
'iblock',
'OnBeforeIBlockElementAdd',
'DoNotAdd'
);
function DoNotUpdate(&$arFields)
{
if ($_REQUEST['mode'] == 'import') {
unset($arFields['PREVIEW_PICTURE']);
unset($arFields['DETAIL_PICTURE']);
unset($arFields['PREVIEW_TEXT']);
unset($arFields['DETAIL_TEXT']);
}
}
function DoNotAdd(&$arFields)
{
if ($_REQUEST['mode'] == 'import') {
unset($arFields['PREVIEW_PICTURE']);
unset($arFields['DETAIL_PICTURE']);
unset($arFields['PREVIEW_TEXT']);
unset($arFields['DETAIL_TEXT']);
}
}
Дополнено: изменение полей товара при обмене с 1С
Написано спустя какое-то время, в обсуждении к заметке описаны случаи когда нужно изменить информацию о товарах, а не о элементах (это немного разное).
Дополняю: обновление габаритов товаров после обмена с 1С, например нужно увеличить все габариты на 1000:
AddEventHandler("iblock", "OnAfterIBlockElementAdd", "UpdateDimensionsAfterElementAddOrUpdate");
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", "UpdateDimensionsAfterElementAddOrUpdate");
function UpdateDimensionsAfterElementAddOrUpdate(&$arFields)
{
if (CModule::IncludeModule("iblock") && CModule::IncludeModule("catalog")) {
if ($_REQUEST['mode'] == 'import' || $_REQUEST['mode'] == 'update') {
// Обновление габаритов (увеличение на 1000 из 1С)
$arProduct = CCatalogProduct::GetByID($arFields['ID']);
if ($arProduct) {
$updatedFields = array(
'WIDTH' => $arProduct['WIDTH'] * 1000,
'LENGTH' => $arProduct['LENGTH'] * 1000,
'HEIGHT' => $arProduct['HEIGHT'] * 1000
);
CCatalogProduct::Update($arFields['ID'], $updatedFields);
}
}
}
}
В этом примере обработчик события UpdateDimensionsAfterElementAddOrUpdate будет срабатывать как при добавлении нового элемента, так и при его обновлении. Внутри обработчика происходит проверка на режим импорта или обновления, и соответственно выполняется обновление габаритов.
Информацию о товаре (как товаре) получаем и обновляем методами CCatalogProduct::GetByID и CCatalogProduct::Update
Возможно ли таким же способом запретить смену типа у свойства при обмене с 1с. Из 1с приходит - строка, а нужно html/text

Цитата |
---|
Владимир написал: Добрый день! Возможно ли таким же способом запретить смену типа у свойства при обмене с 1с. Из 1с приходит - строка, а нужно html/text |
Думаю, будет проще сделать это на выводе, в шаблоне. Используйте вместо
Код |
---|
echo $arResult['DETAIL_TEXT'] |
такой вывод
Код |
---|
echo $arResult['~DETAIL_TEXT'] |

Цитата |
---|
Гость Артур написал: Добрый день, прошу помощи в решении такой проблемы, нужно запретить 1с при обмене, изменять Названия свойств каталога и предложений. |
Тут конечно сходу не подсказать правильный ответ, без экспериментов на живую не обойтись.
Первое что можно попробовать это вот так
Код |
---|
unset($arFields['PROPERTY_*']['NAME']) |
Если не сработает- то вариант жестче:
Получаем название каждого свойства из инфоблока, сохраняем во временную переменную и снова устанавливаем после перезаписи.
Код на вскидку, надо пробовать и дорабатывать, привожу просто в качестве ориентира- куда копать.
Код |
---|
$tmpPropName = $arFields['PROPERTY']['NAME']; /* здесь случилась перезапись */ $arFields = Array( "NAME" => $tmpPropName ); $ibp = new CIBlockProperty; if(!$ibp->Update($ID, $arFields)) |
пробовал варианты:
Код |
---|
if (!empty($_GET['mode']) && $_GET['mode'] == 'import') { unset($arFields); } |
Код |
---|
if (!empty($_GET['mode']) && $_GET['mode'] == 'import') { global $APPLICATION; $APPLICATION->throwException("Пропускаем этот товар " . $arFields['XML_ID']. ' ' . $arFields['NAME']); return false; } |
в первом случае товары добавляются с одним названием
во втором случае товары не добавляются и через некоторое время выгрузка прекращается с ошибкой, указанной в исключении.
при этом, выгрузка прекращается не на первом пропущенном товаре (логировал с помощью AddMessage2Log())
AddEventHandler("catalog", "OnBeforeProductUpdate", Array("My_Class", "OnBeforeProductUpdate"));
Код |
---|
class My_Class { function OnBeforeProductUpdate(&$arFields) { if (@$_REQUEST['mode']=='import')//импорт из 1с? { $arFields["PREVIEW_TEXT"]=$arFields["DETAIL_TEXT"]; } } } |
Подскажите как исправить

Попробуйте использовать OnAfterIBlockElementUpdate
Как-то так, не проверял.
Код |
---|
AddEventHandler("iblock", "OnAfterIBlockElementUpdate", Array("MyClass", "OnAfterIBlockElementUpdateHandler")); class MyClass { // создаем обработчик события "OnAfterIBlockElementUpdate" function OnAfterIBlockElementUpdateHandler(&$arFields) { if ($_REQUEST['mode']=='import') { $arFields["PREVIEW_TEXT"]=$arFields["DETAIL_TEXT"]; } } } |
Есть задача - не передавать названия складов из 1С, а лучше даже менять при выгрузке
В общем нашел такой вариант:
Код |
---|
<? AddEventHandler('catalog', 'OnBeforeCatalogStoreUpdate', 'storeUpdateHandler'); function storeUpdateHandler($storeId, &$arFields) { if (isset($_GET['type'], $_GET['mode']) && $_GET['type'] === 'catalog' && $_GET['mode'] === 'import') { $newStoreTitle = $arFields['TITLE']; $res = CCatalogStore::GetList([],[ "ID" => $storeId ]); if($ar_res = $res->GetNext()) { $oldStoreTitle = $ar_res['TITLE']; if ($newStoreTitle !== $oldStoreTitle) { print_r('На сайте наименование склада #'.$storeId.' ('.$oldStoreTitle.') отличается от наименования в выгрузке ('.$newStoreTitle.'). Наименование не меняем'.PHP_EOL); $arFields['TITLE'] = htmlspecialcharsback($oldStoreTitle); } } } } ?> |
Переделал его как-то под ваш, не знаю правильно или нет
Код |
---|
<? AddEventHandler('catalog', 'OnBeforeCatalogStoreUpdate', 'storeUpdateHandler'); function storeUpdateHandler($storeId, &$arFields) { if ($_REQUEST['mode']=='import') { unset($arFields['TITLE']); } } ?> |
но здесь идет отмена, а как заменить? сможете подсказать

Код |
---|
$arFields['TITLE'] = 'NEW NAME'; |