Руководство по модулю Экспорт на порталы для разработчиков

Есть вопросы, которые вы не смогли решить по нашим публикациям самостоятельно? Ждем ваше обращение в нашей службе техподдержки!

Введение

Модуль «Экспорт на порталы» предназначен для выгрузки товаров из сайта на различные торговые площадки, онлайн-сервисы или социальные сети.

Модуль построен на принципе плагинов (один плагин это интеграция с одним сайтом/сервисом), благодаря чему в модуле имеется возможность интеграции практически с любыми сервисами (текущими и перспективными). Каждая интеграция может быть как простой (одноформатной), так и многоформатной. Например, интеграция с Яндекс.Маркетом разделяется на такие форматы как упрощенный тип, произвольный тип, книги, аудиокниги и т.д. При этом каждый формат в каждой интеграции хоть и основан на общем родителе, но может быть абсолютно самостоятельным.

Модуль использует ядро D7, работает на различных версиях PHP. Возможна выгрузка как прямо со страницы административного раздела, так и с помощью планировщика Cron.


Термины


Автообработка товаров – автоматическая генерация данных для выгрузки товара (XML, CSV, массив данных и др) и сохранение этих данных в БД при: добавлении или изменение товара, свойств, цен, остатков на складах.

Торговая площадка – сторонний сайт или онлайн-сервис, для которого модуль осуществляет выгрузку товаров.

Профиль – совокупность настроек для выгрузки товаров из одного или нескольких инфоблоков на одну торговую площадку.


Общее устройство и работа модуля


Принцип настройки модуля заключается в создании профилей выгрузки для каждого случая, причем каждый профиль можно настроить сразу на все нужные инфоблоки: для каждого инфоблока нужно сначала выбрать его в выпадающем списке, а затем настроить все параметры и поля.

Благодаря оригинальной идее и устройству модуля, можно настроить работу разными способами. Основной сценарий, с использованием автообработки, следующий: модуль отслеживает изменения в имеющихся товарах и добавление новых и автоматически обрабатывает товар по всем настроенным активным профилям, для которых настроена автообработка: в случае, если товар подходит под условия профиля (принадлежность к разделам и фильтры), то информация для этого товара (с привязкой к профилю) сохраняется в отдельную таблицу базы данных, иначе он оттуда удаляется (это первый этап). Таким образом, в указанной таблице хранится вся информация для выгрузки, которая впоследствии (это второй этап) выгружается необходимыми способами (либо в XML, либо по API на сторонние сайта, либо иными способами).

Другой сценарий работы, без автообработки, отличается от вышеописанного тем, что первый этап автоматически не выполняется, он выполняется только в начале второго этапа.

Таким образом, по первому сценарию большая часть нагрузки при экспорте ложится на автообработку («на лету»), при этом сохранение каждого товара будет занимать немного больше времени чем обычно. В случае массовой загрузки товаров из внешних источников (напр., интеграция с 1С или загрузка товаров сторонними модулями) такой сценарий будет увеличивать общее время загрузки товаров (ориентировочно, на 10-30%). Поэтому, если товары загружаются массово, то автообработка не имеет смысла, и ее лучше отключать, в таком случае эта работа будет выполняться при запуске выгрузки, перед вторым этапом.

В случае ручного редактирования товаров (когда объемы изменений небольшие), имеет смысл использовать автообработку, т.к. вся работа по генерации будет проходить автоматически, практически не увеличивая время работы менеджера, а этап выгрузки сгенерированных данных, который в среднем занимает до нескольких секунд (если не учитывать выгрузку в файлы Excel и выгрузку по API на сторонние сайты/сервисы), практически не нагружает сайт.

По второму сценарию нагрузка создается только в момент экспорта, и выполняются оба этапа: сначала генерация, затем выгрузка.

Важное замечание: этап генерации данных (который можно отключить отключением автообработки) выполняется и во втором сценарии, т.к. при первичной настройке профиля с автообработкой данных пока никаких не сгенерировано. Но если модуль определит, что сгенерированы все нужные товары, этот этап сразу же завершается.


Профили


Профиль это совокупность настроек для выгрузки товаров на одну торговую площадку по одной логике, общей для всех инфоблоков в рамках данного профиля. При этом на одну торговую площадку можно настроить сколько угодно профилей, но один профиль может выгружать только на одну торговую площадку.

Структурно, профиль это блок настроек профиля, и блок настроек каждого инфоблока, входящего в состав профиля. Для каждого из этих инфоблоков имеются собственные настройки (в форме редактирования профиля они расположены во вложенных вкладках), а также блок полей, относящихся к инфоблоку. В свою очередь каждое такое поле имеет собственные настройки, а также блок относящихся к нему значений.

Т.е. структура следующая: Профиль – Инфоблок – Поле – Значение поля.

В каждом профиле указывается плагин для загрузки и если плагин имеет несколько форматов- конкретный формат. В зависимости от выбора плагина/формата в профиле появляются дополнительные настройки (напр., итоговый файл или данные для интеграции с торговой площадкой).


Плагины и их структура


Плагин представляет собой обособленный программный код, предназначенный для интеграции модуля с одной конкретной торговой площадкой (напр., плагин для Яндекс.Маркета, плагин для Авито и т.д.). Т.к. в рамках одной торговой площадки могут быть различные варианты выгрузки, модуль предусматривает различные форматы в рамках одного плагина. Например, плагин Яндекс.Маркета имеет такие форматы как упрощенный тип, произвольный тип, книги и т.д.

Плагины модуля хранятся в папке plugins модуля. Важная особенность заключается в том, что программист, без любого вмешательства в код и файлы модуля, может разработать собственную интеграцию с любым сервисом – для этого необходимо использовать обработчик события «OnFindPlugins»: в этом обработчике нет аргументов, все что требуется от разработчика – в этом обработчике подключить файл плагина (разместить его можно, например, в своей папке в папке /bitrix/php_interface/include/) – далее модуль просматривает все подключенные классы-потомки от \Acrit\ExportProPlus\Plugin и из них строит список плагинов.

Структурно плагин представляет собой отдельную папку в общей папке плагинов. В папке плагина должен находиться основной его файл – class.php, а также могут располагаться дополнительные: icon.png (картинка размером 16х16 пикселей), style.css, script.js, .example.php, .description.php. Также в этой папке имеется папка lang для языковых файлов. Если у плагина имеются различные форматы выгрузки – у него должна быть создана папка formats, в которой каждый формат выгрузки реализован отдельной подпапкой аналогично самому плагину.


Структура файла class.php


Файл class.php должен содержать класс, реализовывающий абстрактный класс \Acrit\ExportProPlus\Plugin (см. /lib/plugin.php).

Класс плагина должен иметь следующие основные методы:

getCode – метод должен возвращать символьный код плагина (формата), при этом рекомендуется символьный код формата строить конкатенацией символьного кода плагина, символа подчеркивания и уникального кода формата (напр., если плагин TEST, то формат TEST_1 или TEST_NEW).

getName – метод должен возвращать имя (заголовок) плагина (формата).

getDescription – метод должен возвращать описание плагина (формата), по умолчанию описание берется из файла .description.php, наличие данного метода меняет логику получения описания.

getExample – метод должен возвращать пример генерируемых данные, работает аналогично методу getDescription.

isSubclass – метод должен возвращать false для плагина и true для формата.

Также имеются другие методы, влияющие на процесс настройки и экспорта:

isOffersPreprocess – метод дает возможность указать, что сначала должны обрабатываться предложения, которые не сохраняются отдельно, а затем уже сам товар. Благодаря этому можно выгружать товары, внутри которых будет выгружены торговые предложения.

areAdditionalFieldsSupported – метод должен вернуть true для тех плагинов/форматов, которые поддерживают дополнительные поля (как <param> в Яндекс.Маркет)

areCategoriesExport – метод должен вернуть true, если плагин/формат экспортирует категории в итоговом файле.

isCategoryStrict – метод должен возвращать true, если плагин/формат использует только собственные категории.

hasCategoryList – метод должен возвращать true, если в плагине/формате имеется собственный список категорий.

Другие обязательные методы:

showSettings – метод должен возвращать HTML для показа блока настроек в профиле.

getFields – метод должен возвращать массив полей, доступных для настройки в каждом плагине/формате. Каждый элемент в массиве должен быть класса \Acrit\ExportProPlus\Field\Field. В данном методе имеется возможность задавать общие поля в плагине, а в форматах задавать специфические поля. Для удобства имеются специальные методы работы с этим массивом полей: removeFields (чтобы в формате удалить какие-то поля, заданные в плагине), sortFields (сортировать поля).

processElement – метод, выполняющий основную работу плагина/формата – генерация данных для одного элемента. Метод возвращает массив, описывающий итоговую запись. Вызывается как для товаров, так и для предложений (т.е. один вызов метода на один элемент инфоблока).

getSteps – метод (при его наличии) должен возвращать массив шагов для экспорта данным плагином/профилем. Например, сюда можно добавлять шаги по экспорту в XML, сжатию в ZIP, выгрузке на торговые площадки по API, отправку на другие сайты или по почте, создание отчетов – все что угодно. Каждый элемент массива должен иметь ключ, который является символьным кодом, а сам элемент должен содержать такие ключи как NAME (название шага выгрузки), SORT (индекс сортировки), FUNC (callback-функция, являющаяся методом класса).


Принцип работы плагинов на основе Яндекс.Маркета


Каждый плагин/формат должен иметь собственный набор полей (метод getFields), которые и доступны для заполнения при выборе конкретного инфоблока в форме настройки профиля.

Во время выгрузки (а при автообработке – в момент обработки) товара по данному профилю модуль получает все настроенные поля и их значения, обрабатывает их, и вызывает метод processElement, куда приходят уже обработанные поля (аргумент $arFields). Этот метод, имея указанные данные, собирает из них XML, и возвращает массив, описывающий полученный результат для данного товара (ключи TYPE, DATA, CURRENCY, SECTION_ID и др). Эти данные записываются в таблицу, и впоследствии они отбираются в соответствии с сортировкой и записываются в XML-файл (для записи в файл добавлен шаг EXPORT, для архивации - ZIP).

В функции метода, выполняющего роль шага, имеются два аргумента: первый указывает на ID профиля, второй – на массив с данными, в котором имеется: сессия SESSION (данные о текущей сессии выгрузки, куда можно дописывать свои данные, но только для текущего шага – напр., на шаге EXPORT можно записывать только в ключ $arData['SESSION']['EXPORT']), массив профиля и его настройки PROFILE, массив всех шагов STEPS, данные о текущем шаге CURRENT_STEP_CODE и CURRENT_STEP, а также флаг запуска из планировщика IS_CRON.

Каждый метод-шаг должен вернуть одно из трех значений:

\Acrit\ExportProPlus\Exporter::RESULT_SUCCESS – если процесс завершен, шаг выполнен и можно переходить к следующему шагу.

\Acrit\ExportProPlus\Exporter::RESULT_CONTINUE – если шагу требуется еще запуск (не актуально для вызова из Cron, т.к. в этом случае каждый шаг выполняется за 1 раз, внутри шага пошаговости нет).

\Acrit\ExportProPlus\Exporter::RESULT_ERROR – если шаг завершился с ошибкой, из-за которой нет смысла продолжать процесс. Будет выдана ошибка, процесс завершится.


Настройки полей и значений


Настройки полей и настройки значений это, фактически, одно и то же, как на уровне программной логики, так и на пользовательском уровне. Вся разница между настройками задается в программном коде самих настроек: каждая настройка это отдельный php-класс, в котором можно управлять логикой показа настройки, а также процессом обработки значения текущей настройкой.

Иными словами, такие настройки как «Режим множественных значений», «Преобразовать HTML в текст», «Регистр текста» и др – это все отдельные классы (в /lib/settings/), в которых имеются методы isForFields, isForValues, isShown для управления показом настроек.

Таким образом, все настройки построены по общему принципу, на основе базового класса \Acrit\ExportProPlus\Settings\Base, где основные метод следующие:

getName – получение название,

getCode – получение символьного кода,

getHint – получение подсказки,

getSort – получение индекса сортировки,

getGroup – получение группы (в виде массива, т.к. если необходимо создать свою группу, то нужно указывать не только символьный код, но и название группы),

isForFields – указание что данная настройка действует для полей,

isForValues – указание что данная настройка действует для значений,

showSettings – получение HTML-блока для вывода условий,

process – процесс обработки значения данной настройкой.

Имейте ввиду, что в настройках имеет значение их порядок (SORT), т.к. применение настроен выполняется в порядке возрастания. Таким образом, сначала к «чистому» значению применяется опция 1, затем к уже обработанному значению применяется опция 2 и т.д.

Важно упомянуть и про опцию множественности: данная опция позволяет управлять, какое значение будет в результате обработки. Например, если необходимо чтобы в итоговом файле какой-либо XML-тег «размножился», то для поля настройка «Режим множественных значений» должна иметь значение «Оставить множественным» (имейте ввиду, что данный пункт в данной опции появляется для поля только если в параметрах поля отмечена множественность [MULTIPLE => true, см. getFields() для плагина]).

Таком образом, если в поле указать несколько значений, оно не должно быть множественным. Оно должно быть множественным только если выбран указанный в предыдущем абзаце пункт «Оставить множественным». Иначе имеется возможность перечисления их через запятую или выборка первого непустого значения.

В процессе разработки важно помнить, что опция множественности должна быть первой в списке опций, т.к. в противном случае настройки будут некорректно работать в целом.

Также имеется настройка «Использовать значение без обработки» (код RAW), обработка которой выполняется не в process.php, а в коде модуля. Эта настройка позволяет выгружать не обработанные значения, а исходные. Например, если у товара есть свойство привязки к элементам, данная опция позволит выгружать не название привязанного элемента (само значение хранится в виде числового ID, а название получается уже модулем), а собственно его ID.

Используя событие OnGetAllSettings, разработчик может добавить собственные настройки.


Логирование


В модуле имеется класс \Acrit\ExportProPlus\Log, реализующий простое логирование:

\Acrit\ExportProPlus\Log::add($mMessage, $intProfileID=false);

Где $mMessage это логируемые данные (строка, число, массив, булево или null), а $intProfileID – это ID профиля.

В зависимости от $ intProfileID модуль пишет либо в общий лог, либо в лог профиля. Логи находятся в папке /upload/acrit.exportproplus.


Дополнительные возможности


Для получения языковых фраз удобно использовать не Loc::getMessage(), а static::getMessage(), чтобы не использовать длинные языковые фразы: в таком случае языковые фразы располагаются как бы в своей области имен, например,

static::getMessage(‘NAME’);

равносильно этому:

Loc::getMessage(‘ACRIT_EXP_YANDEX_MARKET_NAME’);

В случае необходимости создания отдельных таблиц в базе данных для плагина/формата – это все необходимо разрабатывать индивидуально в class.php с учетом того, что в модуле нет такого понятия как «установка плагина», поэтому, например, перед созданием таблиц необходимо проверять их наличие.

Для работы с HTTP в модуле имеется класс \Acrit\ExportProPlus\HttpRequest, который умеет делать запросы через cURL или file_get_contents (автоматически выбирается то, что доступно на сервере). Метод getHttpContent используется как раз для выполнения HTTP-запроса, также имеются короткие вызовы для запросов типа GET и POST (одноименные методы).


Особенности работы при запуске из командной строки


Модуль умеет автоматически (кнопка «Настроить автозапуск» на странице редактирования профиля) для каждого профиля настраивать задания планировщика, однако не на всех серверах это доступно. Если на Вашем сервере это недоступно, следует вручную настроить задание на сервере (при наличии панели управления хостингом это делается в панели, иначе – вручную через SSH). В любом случае, текст команды для запуска можно «подсмотреть» во всплывающем окне при настройке автозапуске.

Запуск из командной строки (в т.ч. запуск из планировщика) имеет ряд особенностей. Первая особенность – кодировка. На многих серверах параметры php для сайта и для командной строки в разной степени различаются (особенно это касается настроек mbstring). А необходимы настройки идентичные. Поэтому в команду запуска из планировщика модуль автоматически добавляет конфигурационные параметры mbstring (см. настройки модуля).

Другая особенность – т.к. задание выполняется за один шаг, то на сервер может создаваться высокая нагрузка (особенно, если генерация выполняется не автоматически, а перед экспортом), и на некоторых серверах это может вызвать проблемы, если заданы какие-либо ограничения на нагрузку (например, скрипт после нагрузки в течение 30 секунд может автоматически завершаться, при этом задание не будет до конца выполнено).

При настройке автозапуска не забывайте учитывать версию PHP (см. настройки модуля): сейчас многие хостинг-провайдеры имеют одновременно несколько версий PHP на одном сервере (при чем по умолчанию [/usr/bin/php или же просто php] обычно это версия 5.x, а на сайте используется 7.x), поэтому при настройке автозапуска должна использоваться та же версия, на которой настроен сайт, иначе запуск закончится какой-либо ошибкой вследствие несовместимости работы системы на иной версии PHP.

Итоговая команда может выглядеть по-разному на каждом сервере, т.к. на каждом сервере свои особенности. Пример команды:

/usr/bin/php -d "mbstring.func_overload"=0 -d "mbstring.internal_encoding"=UTF-8 -f /home/bitrix/www/bitrix/modules/acrit.exportproplus/cron/export.php profile=3 start=Y

Здесь profile=3 указывает, что будет выполняться профиль с ID=3, а параметр start=Y – это технический параметр, при этом - обязательный.

Для автоматической настройки требуется указание пути в php. Указать путь в php на своем сайте Вы можете в настройках модуля. Также там имеется возможность включить или отключить добавление в команду параметров mbstring.

Внимание! Первый запуск настоятельно рекомендуем провести через SSH, т.к. в этом случае сразу видны возможные проблемы при настройке, в т.ч. проблемы с отправкой почты. Также, настраивая планировщик, желательно указать свой email в его настройках, чтобы при наличии ошибок сообщения об этом приходили на email.

Внимание! Задания планировщика должны выполняться от имени того же пользователя, от имени которого работает сайт. Иначе возможны проблемы в дальнейшей работе. Так, при использовании виртуальной машины Битрикс, если запускать команды через SSH войдя под пользователем root, задание будет выполняться от имени root, поэтому, если все файлы сайта принадлежат пользователю bitrix, то файлы и папки модуля, создаваемые во время выполнения задачи (в т.ч. генерируемые модулем файлы XML, CSV, Excel и др.) будут принадлежать пользователю root, и сайт не сможет работать с этими файлами (в напр., удалить, переименовать или переместить их).


Стиль и логика написания php-кода


Ввиду большого объема исходного кода модуля, а также ввиду достаточной его сложности, важно понимать и соблюдать правила написания исходного кода. Основные правила следующие:

1)      Все php-файлы должны быть в пространстве имен Acrit\ExportProPlus,

2)      Отступы – только табуляция, пробелы не допускаются.

3)      Открытие фигурной скобки на строке оператора, а не на отдельной строке, дополнительные конструкции (в рамках данной конструкции) начинаются с новой строки, подчиненный код сдвинут на один символ табуляции:
if ($a==$b){
         print "equal";
}
else {
         print "not equal";
}

4)      Лишние пробелы в скобках (условия, циклы, аргументы) не добавляются.

5)      Префиксы для переменных – int (целое число), f (дробное число), str (строка), ar (массив), ob (объект), res (ресурс), b (булево), m (mixed).

6)      Имена переменных, классов, идентификаторов и т.п. должны быть понятными и без сокращений.

7)      В таких именах каждое логическое слово должно начинаться с заглавной буквы. В именах нельзя употреблять подчеркивания для разделения слов.

8)      Длина строки не имеет значения, но в будущем она будет сокращена до 120 символов (при визуальной ширине табуляции в 2 печатных символа).

9)   Все функции и методы, хотя бы очень кратко, но должны быть прокомментированы (желательно English), особенно для сложных случаев:
/**

*     This function starts export

*/

10)   В пределах функции/метода, в сложных случаях, можно разделять логические блоки пустой строкой комментария.

11)   Строковые переменные оформляются, в основном, одинарными кавычками, кроме случаев где использование двойных кавычек оправданно.


Потенциальные вопросы и ответы на них


Что обозначают символы-звездочки в названиях полей (напр., «Название *» или «* Название»)?

Символ звездочки обозначает, что данное поле берется не из данного товара. Оно может браться из первого торгового предложения или из родительского товара (соответственно одна и две звездочки после названия поля), а также из родительского раздела или инфоблока (соответственно одна и две звездочки до названия поля).

При выборе поля для товара можно выбрать данные из его предложений. Из какого предложения будет выбрано значение?

Данные берутся из первого предложения, т.е. учитывается параметр сортировки торговых предложений, и в соответствии с ним выбирается первое предложение. Если у конкретного товара нет предложений, то значение будет пустым.

Можно ли выгружать текст, в котором будут использоваться свойства товара?

Да, для каждого значения поля можно выгружать как значение типа «Поле/свойство», так и просто «Значение» - в последнем случае это простое текстовое поле, но здесь поддерживаются макросы (вида {=properties.PROPERTY_COLOR}). Также, отметив в настройках галочку «Использовать как математическую формулу», можно использовать строку как арифметическое значение. Если при этом отметить галочку «Использовать php-функцию eval()», то подсчет осуществляется функцией eval, т.о. можно производить не только вычисления, но и использовать практически любые php-функции.

Как для поля с описанием применить CData?

Формат CData можно использовать только для тех полей, для которых такая возможность включена (т.е. при объявлении поля задано CDATA => true). Такой формат применяется только к полю в целом, а не отдельно к каждому значению. Т.к. в этом поле допускается использование HTML-символов, то в самих значениях нужно выставлять опции «Спецсимволы» значение «Оставить как есть», а в настройках поля в этой же опции указать «Формат CData».

Как создать свой первый плагин?

Для начала необходимо хотя бы в общих чертах понять принцип работы модуля (ознакомиться с руководством). Затем нужно открыть для изучения один из существующих плагинов, напр., Avito. Плагин это, условно, класс. В классе имеются некоторые описательные методы (для получения названия, кода, описания и т.д.), метод getFields для получение всех доступных полей плагина, а также метод processElement, который обрабатывает один товар. Эти методы являются основополагающими.

Далее, могут возникнуть ситуации, когда необходимо что-то нестандартное. В таком случае это все реализуется прямо в этом же классе, причем если для плагина имеются различные форматы, то целесообразно общий код писать в общем классе плагина. В таком случае код получится красивым и лаконичным.

Если появляются трудности или вопросы – пожалуйста, обращайтесь к разработчикам модуля.

У меня не работает автонастройка планировщика. Как настроить вручную?

Автонастройка это очень удобная вещь, но на некоторых серверах возможность такой автонастройки отсутствует. В таких случаях необходимо настраивать вручную. Если в настройках модуля указано правильно путь к php, то достаточно зайти в профиль, скопировать команду и настроить ее на планировщик. Имейте ввиду, что это будет команда, а не PHP-скрипт! Если Ваш хостинг предоставляет возможность настроить планировщик для PHP-скрипта, то нужно убрать часть команды до начала пути к скрипту.

Как определить путь к PHP на сервере?

Если у Вас используется виртуальная машина Битрикс, то указывайте просто «/usr/bin/php» или если хотите еще проще – «php».

Такой же вариант используется на многих других типов серверов.

Если у Вас не виртуальная машина, то самый простой вариант – спросить в техподдержке хостинга (указав версию PHP, на которой работает сайт).

Как происходит сортировка товаров в генерируемом файле?

В таблицу сгенерированных данных товары попадают в порядке увеличения их ID. При этом к каждой записи вычисляется значение SORT в соответствии с настройками профиля для сортировки. При выгрузке же товары сортируются именно по данному полю SORT. При этом, если две и более записи имеют равное значение SORT (в т.ч. пустые), сортировка выполняется по ID товара.

После настройки профиля и первой выгрузки я поменял настройки профиля. Нужно ли перегенерировать товары?

При каждом сохранении профиля автоматически выполняется удаление сгенерированных данных для этого профиля. Т.к. сгенерированных данных не остается, то они будут сгенерированы при следующем запросе (следующая выгрузка пройдет дольше обычного).




Назад в раздел