Реализация экспорта товаров из сайта в CSV/Excel/XML/JSON
Недавно к нам пришёл клиент: интернет-магазин с 50 000 товаров. Маркетплейсы требовали XML и CSV в разных форматах, бухгалтерия — Excel для 1С, а аналитикам нужен был JSON. Каждый раз разработчики писали новый скрипт, тратя дни. Ошибки в маппинге полей приводили к тому, что на Wildberries уезжала цена без НДС. Это типичная ситуация для растущего бизнеса, когда отделы запрашивают разные форматы, а единого решения нет.
Мы предложили единую архитектуру — паттерн Builder + Writer. Она закрывает все сценарии без дублирования кода. Теперь клиент выбирает шаблон экспорта из админки, жмёт «Скачать» и получает файл нужного формата за секунды.
Почему гибкий экспорт — это сложно?
- Разные форматы: CSV не поддерживает вложенные данные, XML — стандарт для 1С и маркетплейсов, JSON удобен для API, но при размере >50 МБ лучше использовать NDJSON.
- Каждый получатель хочет свой набор полей: для «Яндекс.Маркета» нужны артикул, название, цена, остаток, для Instagram — только фото и ссылка.
- Объём данных: каталог может расти до сотен тысяч позиций. Простой
json_encodeв память «уронит» сервер.
Как работает асинхронный экспорт?
Для больших каталогов экспорт запускается в фоне через очередь. Job получает конфигурацию шаблона, итерирует товары чанками по 1000 записей и передаёт их в Writer. Пользователь получает уведомление о готовности файла. Это позволяет не блокировать сайт и выгружать даже миллионы товаров.
Как мы строим экспорт: паттерн Builder + Writer
Мы разделили логику формирования данных (Builder) и запись в файл (Writer). Builder получает цепочку методов для настройки полей и фильтров, затем запускает итерацию по БД чанками и передаёт строки в Writer.
interface ExportWriterInterface { public function open(string $filePath): void; public function writeHeader(array $columns): void; public function writeRow(array $row): void; public function close(): string; // возвращает путь к файлу } Builder хранит конфиг и умеет разрешать связанные поля (категория, изображения, атрибуты) через match-выражение. Пример для CSV: добавляем BOM для Excel, используем fputcsv с разделителем ;.
class CsvWriter implements ExportWriterInterface { private $handle; public function open(string $filePath): void { $this->handle = fopen($filePath, 'w'); fwrite($this->handle, "\xEF\xBB\xBF"); } public function writeHeader(array $columns): void { fputcsv($this->handle, $columns, ';', '"'); } public function writeRow(array $row): void { fputcsv($this->handle, $row, ';', '"'); } public function close(): string { fclose($this->handle); return $this->filePath; } } Для Excel используем потоковый OpenSpout — он пишет строки напрямую в ZIP-поток, потребляя ~10 МБ памяти при любом размере файла. JSON для больших объёмов — через NDJSON (по объекту в строке). XML — через XMLWriter с элементами <product>.
Таблица сравнения форматов
| Формат | Производительность | Размер файла | Вложенность | Рекомендуемый объём |
|---|---|---|---|---|
| CSV | высокая | маленький | нет | до 100 000 строк |
| XLSX | средняя | средний | нет | до 1 000 000 строк (с OpenSpout) |
| XML | низкая | большой | да | до 50 000 товаров |
| JSON/NDJSON | высокая | средний | да | до 500 000 объектов (NDJSON) |
Сравнение ручного и автоматического экспорта
| Параметр | Ручной (каждый раз новый скрипт) | Автоматический (Builder + Writer) |
|---|---|---|
| Время на разработку нового формата | 1-2 дня | 0 (выбор шаблона) |
| Ошибки маппинга | частые | исключены (единый конфиг) |
| Производительность при большом объёме | медленно, падение памяти | потоково, ~10 МБ |
| Поддержка новых требований | полный переписывание | добавление поля в Builder |
Пример конфигурации Builder
$builder = new ProductExportBuilder(); $builder->addField('sku', function ($product) { return $product->sku; }) ->addField('name', function ($product) { return $product->name; }) ->addField('price', function ($product) { return round($product->price, 2); }) ->addField('category', function ($product) { return $product->category->name; }) ->filterBy('price', '>', 100) ->chunkSize(1000); Что входит в реализацию
- Разработка Builder'a с поддержкой кастомных полей, фильтров и чанкирования (1000 записей).
- Набор Writer'ов для CSV (с BOM), XLSX (OpenSpout), XML, JSON (включая NDJSON).
- Асинхронный экспорт для больших файлов: товары выгружаются в фоне через очередь, пользователь получает уведомление.
- Шаблоны экспорта — хранятся в БД, могут включать трансформации (округление цен, обрезка изображений).
- Готовая страница скачивания с контролем доступа и MIME-типами.
- Документация по настройке шаблонов и развертыванию.
Сколько времени занимает?
- Базовая версия (CSV + Excel + Builder с чанкированием) — 2 дня.
- Добавление XML, JSON, NDJSON и асинхронного Job — +1 день.
- Шаблоны, трансформации, скачивание — +1 день.
Итоговая стоимость рассчитывается индивидуально после анализа объёма и сложности каталога. Свяжитесь с нами — оценим проект в течение одного рабочего дня.
Наши инженеры имеют 5+ лет опыта в Laravel и PHP. Мы реализовали экспорт для магазинов с каталогами до 500 000 товаров. Гарантируем, что файлы будут совместимы с 1С, вашими маркетплейсами и BI-системами. Закажите реализацию под ключ — получите гибкий экспорт, который сэкономит часы ваших разработчиков.







