Выгрузка каталога в файл - прайс-лист, отбор, расписание
Собираем прайс-лист из каталога: с ценами, остатками и отбором, без падения по памяти и без часового ожидания в браузере.
Решение
Открываем файл и пишем заголовок:
$fp = fopen('/home/bitrix/www/upload/price/price.csv', 'w');fwrite($fp, "\xEF\xBB\xBF"); // метка кодировки для таблицfputcsv($fp, ['Артикул', 'Название', 'Цена', 'Остаток'], ';');// разделитель точка с запятой: с ним таблицы разбирают строки без вопросовМетка кодировки в начале файла и точка с запятой как разделитель - два условия того, что файл откроется в табличном редакторе сразу. Без них получается знакомая картина: одна колонка с непонятными символами.
Обходим каталог порциями и пишем строки:
$lastId = 0;while (true) { $res = CIBlockElement::GetList(['ID' => 'ASC'], ['IBLOCK_ID' => 5, 'ACTIVE' => 'Y', '>ID' => $lastId], false, ['nTopCount' => 500], ['ID', 'NAME', 'PROPERTY_CML2_ARTICLE']); $rows = 0; while ($row = $res->Fetch()) { $lastId = $row['ID']; $rows++; /* запись ниже */ } if (!$rows) { break; }}Файл пишут построчно, а не собирают целиком в памяти. Каталог на десятки тысяч позиций в одном массиве - это гарантированное падение по памяти, а построчная запись работает на любом объёме.
Добавляем цены и остатки:
$price = CCatalogProduct::GetOptimalPrice($row['ID'], 1, ['2']); // группа покупателей$product = CCatalogProduct::GetByID($row['ID']);fputcsv($fp, [$row['PROPERTY_CML2_ARTICLE_VALUE'], $row['NAME'], $price['DISCOUNT_PRICE'] ?? '', $product['QUANTITY'] ?? 0], ';');Цена зависит от группы покупателя, и в прайсе это решают явно и заранее. Файл «для всех» с розничной ценой и файл для оптовиков - разные выгрузки, а не одна с пометкой в шапке.
Ставим выгрузку в расписание:
30 4 * * * /usr/bin/php /home/bitrix/www/local/tools/price.php >> /var/log/price.log 2>&1# ночью каталог не мешает посетителям, а файл готов к началу рабочего дняДолгую выгрузку каталога запускают вне окна браузера. Ночной запуск снимает и вопрос ограничения времени выполнения, и вопрос нагрузки: тяжёлая выборка не борется за базу с посетителями.
Отбор для прайса стоит держать точно таким же, как и на витрине сайта. Файл, где есть снятые с продажи позиции, возвращается вопросами от клиентов, а расхождение с сайтом подрывает доверие к обоим источникам.
Готовый файл кладут в место, закрытое от посторонних глаз. Прайс-лист с оптовыми ценами в открытом каталоге загрузок находится поисковой системой за неделю и живёт в её выдаче ещё месяц.
Проверять стоит не только сам факт создания файла, но и число строк. Пустой или вдвое короче обычного файл означает, что отбор изменился или обмен что-то выключил, а узнать об этом лучше раньше клиентов.
Типичные проблемы
Таблица открывает файл одной колонкой.
Разделитель не тот, которого ждёт табличный редактор. С точкой с запятой строки разбираются вообще без настроек.
Вместо русских букв нечитаемые символы.
В самом начале файла нет метки кодировки. Табличный редактор определяет кодировку файла именно по ней.
Скрипт падает по памяти.
Данные собираются в общий массив вместо построчной записи. Каталог целиком в память процесса не помещается.
В прайсе цены не той группы.
Цена взята без указания группы покупателя. Розничная и оптовая цены - это две разные выгрузки, а не одна общая.
Оптовый прайс нашли в поиске.
Файл лежит в открытом всем каталоге загрузок. Такие файлы кладут в закрытое место либо отдают только по проверке прав.
Частые вопросы
В каком формате отдавать прайс?
Текстовым файлом с разделителем: он открывается везде и весит мало. Готовые таблицы нужны реже, чем кажется.
Как отдать прайс только своим?
Скриптом с проверкой прав, который читает файл из закрытого каталога. Ссылка на файл в открытом каталоге проверкой не является.
Сколько строк выдержит выгрузка?
Любое число при построчной записи: ограничение только по времени. Сотня тысяч позиций укладывается в минуты.
Как выгрузить с картинками?
Столбцом с адресами картинок, а не файлами. Архив с изображениями собирают отдельно и по запросу.
Смежное
-
Каталог товаров - оглавление подтемы
-
Импорт товаров из CSV: соответствие колонок, кодировка, обновление - обратная задача
-
Выгрузка в Excel из кода: библиотека, объём, отдача файла - та же выгрузка, но в таблицу
-
Массовая правка товаров: обновление свойств скриптом - тот же обход порциями
-
Свой агент и задание по расписанию: создание, шаг, защита - как поставить выгрузку в расписание
-
Каталог и продажи - устройство магазина целиком
-
Сверка каталога после обмена: числа, расхождения, отчёт - те же разрезы каталога в отчёте
-
Аудит каталога: товары без цены, картинок, дубли артикулов - что проверить до сборки прайса