Задача: прочитать txt-файл с ценами и остатками, который выгружает программа учета по FTP, и обновить эти данные в каталоге. Скрипт должен автоматически запускаться каждую ночь в 00:00 по расписанию.
Считываем txt файл по строчно, с формированием массива
Каждый день, в 11 вечера, программа учета выгружает по FTP текстовый файл в котором каждая строка содержит:
- Уникальный ID товара, который хранится в свойстве элемента инфоблока. В моем случае, свойство имеет код ATT_UNICAL_ID
- Число с остатком товара
- Число с новой ценой товара
![Обновление цен и остатков, в каталоге 1C-Битрикс, из текстового файла.](/upload/medialibrary/3e4/1pt3m9x0caf01ayp7qxnjp78dqs0xaky/1.jpg)
Создаем файл update_products_cron.php и размещаем его в директории /bitrix/php_interface/cron_events. В этом файле, сразу подключаем ядро 1С-Битрикс и модули инфоблоков и каталога, пригодятся дальше. Отключаем сбор статистики и сбрасываем лимит времени на выполнение, в переменной $IBlockId храниться ID инфоблока товары которого нужно обновлять.
Для начала, чтобы считать файл с помощью PHP и преобразовать каждую строку в элемент массива, можно использовать функцию file():.
$_SERVER['DOCUMENT_ROOT'] = realpath(dirname(__FILE__) . '/../../..');
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('BX_NO_ACCELERATOR_RESET', true);
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
@set_time_limit(0);
@ignore_user_abort(true);
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
Loader::includeModule('catalog');
$Update_Catalog = $_SERVER['DOCUMENT_ROOT'] . '/upload/txt_exchange/Update_Catalog.txt';
if (file_exists($Update_Catalog)) {
$IBlockId = 1;
$arFileLines = file($Update_Catalog, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
var_dump($arFileLines)
}
Функция file() считывает файл построчно и возвращает массив строк. Опции FILE_IGNORE_NEW_LINES и FILE_SKIP_EMPTY_LINES удаляют переносы строк и пустые строки соответственно. В примере добавлена проверка на существование файла с помощью функции file_exists().
В итоге, каждая строка из текстового файла станет элементом массива $arFileLines
Получаем элементы раздела зная значения свойства
Дальше нам нужно разбить каждую строку на массив, с помощью функции explode(), в качестве разделителя использовав пробел. Прходимся с помощью foreach по массиву со строками ($arFileLines) и превращаем каждую строку в массив:
foreach ($arFileLines as $arFileLine) {
$arItem = explode(' ', $arFileLine); // Разбираем каждую строку на массив
var_dump($arItem)
}
Теперь нужно найти элементы инфоблока, зная первый ключ этого массива, по значению свойства ATT_UNICAL_ID. Внутри вывода каждого элемента, обновляем доступное количество товара и стоимость товара. Привожу скрипт целиком, пояснения ниже.
$_SERVER['DOCUMENT_ROOT'] = realpath(dirname(__FILE__) . '/../../..');
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS', true);
define('BX_NO_ACCELERATOR_RESET', true);
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
@set_time_limit(0);
@ignore_user_abort(true);
use Bitrix\Main\Loader;
Loader::includeModule('iblock');
Loader::includeModule('catalog');
$Update_Catalog = $_SERVER['DOCUMENT_ROOT'] . '/upload/txt_exchange/Update_Catalog.txt';
if (file_exists($Update_Catalog)) {
$IBlockId = 1;
$arFileLines = file($Update_Catalog, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($arFileLines as $arFileLine) {
$arItem = explode(' ', $arFileLine);
$getItem = CIBlockElement::GetList (
false,
Array(
'IBLOCK_ID' => $IBlockId,
'PROPERTY_ATT_UNICAL_ID' => $arItem['0']
),
false,
false,
Array(
'ID'
)
);
while($arFields = $getItem->Fetch())
{
$productFields['QUANTITY'] =$arItem['1'];
CCatalogProduct::Update(
$arFields['ID'],
$productFields
);
CPrice::SetBasePrice(
$arFields['ID'],
$arItem['2'],
"RUB"
);
}
}
}
- В переборе массива $arFileLines приводим каждую строку к массиву $arItem и с помощью CIBlockElement::GetList получаем ID товара с кодом ATT_UNICAL_ID (значение в первом элементе массива $arItem['0'], из строки).
- С помощью CCatalogProduct::Update устанавливаем доступное количество товара из второго элемента массива $arItem['1']
- С помощью CPrice::SetBasePrice устанавливаем цену товара из третьего элемента массива $arItem['2']
Далее, вешаем этот скрипт на выполнение, с помощью crontab на каждый день в 00:00. Скрипт отрабатывает достаточно быстро и не подвешивает сайт. В моем случае, в каталоге около 50 000 товаров, обрабатываются за 7-8 минут.
![](/upload/resize_cache/forum/avatar/35f/30_30_2/111111.jpg)
Код |
---|
if ($arItem['1'] > 0) { $ostatok = $arItem['1']; } else { $ostatok = 0; } |