Розробка модуля експорту даних 1С-Бітрікс
Експорт із Бітрікс — завдання на перший погляд просте: SELECT із потрібних таблиць і сформувати файл. На практиці все складніше: дані розподілені по десятках таблиць, потрібні JOIN з урахуванням прав доступу, файл має генеруватися асинхронно без блокування інтерфейсу, а формати можуть відрізнятися залежно від отримувача.
Типові сценарії
- Вивантаження каталогу для маркетплейсів (Ozon, Wildberries) у специфічному XML або JSON
- Експорт замовлень до 1С:Бухгалтерії через XML або CSV
- Регулярне вивантаження лідів CRM до Google Sheets або BI-системи
- Передача даних користувачів до ESP (UniSender, SendGrid)
- Резервний експорт даних для переносу на іншу платформу
Для кожного сценарію — свій маппінг полів і свій формат. Єдиний модуль дозволяє налаштувати всі вивантаження в одному місці.
Структура модуля
Модуль vendor.exporter із трьома шарами:
- Collector — збирає дані з джерела (ORM-запити до таблиць Бітрікс)
- Transformer — перетворює сирі дані на потрібну структуру
- Formatter — формує кінцевий файл потрібного формату
Таблиці модуля:
-
b_vendor_exporter_profile— профілі експорту: name, source_config (JSON), format, schedule, last_run, last_file -
b_vendor_exporter_job— завдання на експорт: profile_id, status, started_at, finished_at, file_path, rows_count, error -
b_vendor_exporter_field— маппінг полів для профілю: profile_id, source_field, target_field, transform_rule
Колектори даних
class CatalogProductCollector implements CollectorInterface
{
public function collect(array $filter, array $select): \Generator
{
$query = \Bitrix\Iblock\Elements\ElementTable::query()
->setFilter($filter)
->setSelect($select);
foreach ($query->fetchAll() as $row) {
// JOIN із цінами
$prices = \Bitrix\Catalog\PriceTable::getList([
'filter' => ['=PRODUCT_ID' => $row['ID']],
'select' => ['PRICE', 'CURRENCY', 'CATALOG_GROUP_NAME'],
])->fetchAll();
$row['PRICES'] = $prices;
yield $row;
}
}
}
Використання Generator замість масиву критично при вивантаженні 100 000+ записів — дані не накопичуються в пам'яті.
Форматери
CSV-форматер із підтримкою роздільників і кодувань:
class CsvFormatter implements FormatterInterface
{
public function format(\Generator $data, array $columns, string $outputPath): void
{
$handle = fopen($outputPath, 'w');
fputs($handle, "\xEF\xBB\xBF"); // UTF-8 BOM для Excel
fputcsv($handle, array_column($columns, 'label'), $this->delimiter);
foreach ($data as $row) {
fputcsv($handle, $this->extractValues($row, $columns), $this->delimiter);
}
fclose($handle);
}
}
XML-форматер для довільних схем — налаштовується шаблоном XSD або XSLT. XLSX-форматер через PhpSpreadsheet із підтримкою форматування комірок. JSON-форматер із вибором структури: плаский масив або вкладені об'єкти.
Асинхронна генерація
Файл не генерується синхронно при HTTP-запиті. Адміністратор натискає «Запустити експорт», створюється завдання в b_vendor_exporter_job зі статусом queued. Агент ExportAgent::run() запускається раз на хвилину:
public static function run(): string
{
$job = ExportJobTable::getList([
'filter' => ['=STATUS' => 'queued'],
'order' => ['CREATED_AT' => 'ASC'],
'limit' => 1,
])->fetch();
if (!$job) return __CLASS__ . '::run();';
ExportJobTable::update($job['ID'], ['STATUS' => 'running', 'STARTED_AT' => new DateTime()]);
try {
$profile = ExportProfileTable::getById($job['PROFILE_ID'])->fetch();
$service = new ExportService($profile);
$filePath = $service->execute();
ExportJobTable::update($job['ID'], [
'STATUS' => 'done',
'FILE_PATH' => $filePath,
'FINISHED_AT' => new DateTime(),
]);
} catch (\Throwable $e) {
ExportJobTable::update($job['ID'], ['STATUS' => 'failed', 'ERROR' => $e->getMessage()]);
}
return __CLASS__ . '::run();';
}
Розклад та автодоставка
Профілі підтримують cron-розклад. Після генерації файл можна:
- завантажити вручну з адміністративного інтерфейсу
- надіслати на email (через
\Bitrix\Main\Mail\Event::send()) - передати по FTP/SFTP (
\Bitrix\Main\IO+ PHP ftp-функції) - опублікувати за URL (файл кладеться до
/upload/vendor_exporter/, посилання фіксується в профілі) - надіслати POST-запитом до зовнішнього API (webhook із файлом у multipart/form-data)
Фільтрація та частковий експорт
У профілі налаштовується базовий фільтр. При ручному запуску адміністратор може доповнити фільтр через форму: діапазон дат, статуси, конкретні ID. Фільтр передається до колектора через filter_override:
$collector->collect(
array_merge($profile->getBaseFilter(), $job->getFilterOverride()),
$profile->getSelect()
);
Безпека та права
Експорт персональних даних (користувачі, замовлення) доступний лише групам із явно наданими правами в налаштуваннях модуля. Логується: хто запустив експорт, коли, скільки записів, шлях до файлу. Лог зберігається в b_vendor_exporter_audit.
Терміни розробки
| Етап | Термін |
|---|---|
| Архітектура, інтерфейси, таблиці | 1 день |
| Колектори для потрібних сутностей Бітрікс | 2 дні |
| Форматери (CSV, XML, XLSX, JSON) | 2 дні |
| Асинхронна генерація, агент | 1 день |
| Розклад, автодоставка (email, FTP) | 2 дні |
| Адміністративний інтерфейс | 2 дні |
| Фільтрація, права, аудит-лог | 1 день |
| Тестування на великих обсягах | 1 день |
Разом: 12 робочих днів для стандартного набору форматів і джерел. Специфічні формати маркетплейсів (особливо з обов'язковими полями сертифікації) — +1–2 дні кожен.







