YML-файл для трансляции товаров на Яндекс.Маркете (скрипт для osCommerce 2.3)

Default Image Лаборатория Кода

Рано или поздно для интернет-магазинов возникает необходимость вывода товаров на Яндекс.Маркет. Это мощный канал привлечения клиентов: по статистике Яндекса, миллионы покупателей по всей России выбирают этот сервис, чтобы сравнить цены и найти лучшее предложение.

Для передачи данных о товарах Яндекс.Маркет требует загрузить прайс-лист в особом формате — YML (Yandex Market Language), который является разновидностью XML. Такой файл можно генерировать динамически с помощью PHP. В этой статье я подробно расскажу, как создать его для магазина на движке osCommerce.

Как это работает: от регистрации до выгрузки

После регистрации магазина на Яндекс.Маркете вам необходимо будет указать ссылку на ваш прайс-лист. По этой ссылке должен располагаться скрипт (в нашем случае — ya-market.php), который при каждом обращении со стороны Яндекса будет динамически формировать актуальный YML-файл, обращаясь к базе данных вашего магазина.

Почему я написала свой скрипт? В интернете я нашла несколько готовых решений для osCommerce, но в моем случае они оказались непригодными — либо устаревшими, либо содержащими ошибки. Поэтому я полностью переписала один из найденных PHP-файлов, исправив логику, код и адаптировав его под современные требования. Ниже представлен итоговый рабочий код с подробными комментариями.

Создание YML-файла: Пошаговый разбор кода

Шаг 1: Заголовок и подключение к базе данных

Первым делом скрипт должен сообщить, что он выдает XML, и подключиться к базе данных MySQL, где хранятся все данные osCommerce.

<?php
// Устанавливаем заголовок для вывода XML
header("Content-Type: application/xml; charset=utf-8");

// Параметры подключения к БД. ЗАМЕНИТЕ ИХ НА СВОИ!
$db_host = 'localhost';      // Адрес сервера БД
$db_user = 'username';       // Имя пользователя БД
$db_pass = 'password';       // Пароль пользователя БД
$db_name = 'database_name';  // Имя базы данных магазина

// Устанавливаем соединение
$dbc = mysqli_connect($db_host, $db_user, $db_pass, $db_name);
if (!$dbc) {
    die('Ошибка подключения: ' . mysqli_connect_error());
}

// Важно: Устанавливаем корректную кодировку соединения.
// Если ваша БД использует кодировку latin1, укажите её.
// Для современных магазинов рекомендуется utf8.
mysqli_set_charset($dbc, 'latin1');
?>

Шаг 2: Формирование «шапки» YML-файла

Начинаем генерировать XML, добавляя обязательные элементы: информацию о магазине, валютах и времени создания файла.

<?php
// Данные вашего магазина для заголовка YML
$cdate = date("Y-m-d H:i"); // Текущая дата и время
$csite = "http://www.moy-sayt.ru/"; // Вписать адрес интернет-магазина
$cname = "Название вашего магазина"; // Вписать название интернет-магазина
$cdesc = "Подробное описание вашего интернет-магазина"; // Вписать описание

// Начинаем формировать XML-структуру
$yandex = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$yandex .= '<!DOCTYPE yml_catalog SYSTEM "shops.dtd">' . "\n";
$yandex .= '<yml_catalog date="' . $cdate . '">' . "\n";
$yandex .= '  <shop>' . "\n";
$yandex .= '    <name>' . htmlspecialchars($cname) . '</name>' . "\n";
$yandex .= '    <company>' . htmlspecialchars($cname) . '</company>' . "\n";
$yandex .= '    <url>' . $csite . '</url>' . "\n";
$yandex .= '    <platform>osCommerce</platform>' . "\n";
$yandex .= '    <currencies>' . "\n";
$yandex .= '      <currency id="RUR" rate="1"/>' . "\n"; // Основная валюта - российский рубль
$yandex .= '    </currencies>' . "\n";
?>

Шаг 3: Выгрузка категорий товаров

В osCommerce данные о категориях обычно разделены между двумя таблицами. Нам нужен запрос, который объединит categories (ID и родительская категория) и categories_description (названия).

<?php
// Массив для хранения категорий (может пригодиться для дополнительной логики)
$arr_cats = array();

// Открываем блок <categories>
$yandex .= '    <categories>' . "\n";

// Запрос для получения всех категорий и подкатегорий
$tmp = "SELECT c.categories_id as categoryID, 
               cd.categories_name as name, 
               c.parent_id as parent
        FROM categories as c, 
             categories_description as cd 
        WHERE c.categories_id = cd.categories_id 
          AND cd.language_id = 2
        ORDER BY parent, name";

$res = mysqli_query($dbc, $tmp);

while ($row = mysqli_fetch_assoc($res)) {
    // Экранируем специальные XML-символы в названии категории
    $category_name = htmlspecialchars($row['name']);

    // Формируем XML-тег категории
    $category_xml = '      <category id="' . $row['categoryID'] . '"';

    // Если у категории есть родитель, добавляем атрибут parentId
    if ($row['parent'] > 0) {
        $category_xml .= ' parentId="' . $row['parent'] . '"';
    }

    $category_xml .= '>' . $category_name . '</category>' . "\n";

    // Добавляем сформированную строку в общий XML
    $yandex .= $category_xml;

    // Сохраняем категорию в массив (опционально, для возможного дальнейшего использования)
    $arr_cats[$row['categoryID']] = $row;
}

// Закрываем блок <categories>
$yandex .= '    </categories>' . "\n";
?>

Что получится в итоге (пример вывода категорий):

<categories>
  <category id="1">ДИСКИ</category>
  <category id="2">ШИНЫ</category>
  <category id="10" parentId="1">Диски AUDI</category>
  <category id="11" parentId="1">Диски BENTLEY</category>
  <category id="12" parentId="1">Диски BMW</category>
  <category id="13" parentId="1">Диски CADILLAC</category>
  <category id="14" parentId="1">Диски CHEVROLET</category>
  <category id="15" parentId="1">Диски HUMMER</category>
  <category id="16" parentId="1">Диски INFINITY</category>
  <category id="17" parentId="1">Диски LAND ROVER</category>
  <category id="18" parentId="1">Диски LEXUS</category>
  <category id="19" parentId="1">Диски MERCEDES</category>
  <category id="20" parentId="1">Диски NISSAN</category>
  <category id="21" parentId="1">Диски PORSCHE</category>
  <category id="22" parentId="1">Диски SUBARU</category>
  <category id="23" parentId="1">Диски TOYOTA</category>
  <category id="24" parentId="1">Диски VOLKSWAGEN</category>
  <category id="25" parentId="1">Диски VOLVO</category>
  <category id="30" parentId="2">Б/У покрышки</category>
  <category id="31" parentId="2">Шины. Зима</category>
  <category id="32" parentId="2">Шины. Лето</category>
</categories>

Шаг 4: Выгрузка товарных предложений (offers)

Это самая важная часть — вывод непосредственно товаров. Мы выбираем товары, которые активны, имеют цену и привязаны к категориям.

<?php
// Открываем блок <offers>
$yandex .= '    <offers>' . "\n";

// Запрос для получения товаров
$tmp = "SELECT p.products_id AS productID,
               p.products_price AS Price,
               p.products_image AS picture,
               p.products_status AS in_stock,
               pd.products_name AS name,
               pd.products_description AS brief_description,
               pc.categories_id AS categoryID
        FROM products AS p,
             products_description AS pd,
             products_to_categories AS pc
        WHERE p.products_price > 0
          AND pd.products_id = p.products_id
          AND pc.products_id = p.products_id
          AND p.products_status = 1
          AND pd.language_id = 2
        ORDER BY name";

$res = mysqli_query($dbc, $tmp);

while ($tovar = mysqli_fetch_assoc($res)) {
    // Подготовка данных товара
    $valuta = "RUR"; // Валюта: российский рубль
    $price = intval($tovar['Price']); // Цена (целое число)

    // Очищаем описание от HTML-тегов и экранируем спецсимволы
    $description = htmlspecialchars(strip_tags($tovar['brief_description']));

    // Экранируем название товара
    $product_name = htmlspecialchars($tovar['name']);

    // Формируем ссылку на товар (важно: структура URL зависит от вашего магазина)
    $product_url = $csite . 'catalog/' . $tovar['categoryID'] . '-p-' . $tovar['productID'] . '.html';

    // Формируем ссылку на изображение товара, если оно есть
    $picture_xml = '';
    if (!empty($tovar['picture'])) {
        $src_file = $csite . 'catalog/images/' . $tovar['picture'];
        $picture_xml = '        <picture>' . htmlspecialchars($src_file) . '</picture>' . "\n";
    }

    // Формируем XML для одного товарного предложения
    $yandex .= '      <offer id="' . $tovar['productID'] . '" available="true">' . "\n";
    $yandex .= '        <url>' . $product_url . '</url>' . "\n";
    $yandex .= '        <price>' . $price . '</price>' . "\n";
    $yandex .= '        <currencyId>' . $valuta . '</currencyId>' . "\n";
    $yandex .= '        <categoryId>' . $tovar['categoryID'] . '</categoryId>' . "\n";
    if (!empty($picture_xml)) {
        $yandex .= $picture_xml;
    }
    $yandex .= '        <name>' . $product_name . '</name>' . "\n";
    $yandex .= '        <description>' . $description . '</description>' . "\n";
    $yandex .= '      </offer>' . "\n\n";
}

// Закрываем блок <offers>
$yandex .= '    </offers>' . "\n";
?>

Шаг 5: Завершение XML и вывод результата

<?php
// Закрываем оставшиеся теги
$yandex .= '  </shop>' . "\n";
$yandex .= '</yml_catalog>';

// Закрываем соединение с базой данных
mysqli_close($dbc);

// Выводим сгенерированный XML
echo $yandex;
?>

Пример итогового YML-файла (сокращенная версия)

Вот как выглядит полный YML-файл, сгенерированный нашим скриптом (для наглядности представлены только первые несколько товаров):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE yml_catalog SYSTEM "shops.dtd">
<yml_catalog date="2023-12-20 14:30">
  <shop>
    <name>Колесные диски и шины</name>
    <company>Колесные диски и шины</company>
    <url>http://www.moy-sayt.ru/</url>
    <platform>osCommerce</platform>
    <currencies>
      <currency id="RUR" rate="1"/>
    </currencies>
    <categories>
      <category id="1">ДИСКИ</category>
      <category id="2">ШИНЫ</category>
      <category id="10" parentId="1">Диски AUDI</category>
      <category id="11" parentId="1">Диски BENTLEY</category>
      <category id="12" parentId="1">Диски BMW</category>
      <!-- ... остальные категории ... -->
      <category id="31" parentId="2">Шины. Зима</category>
      <category id="32" parentId="2">Шины. Лето</category>
    </categories>
    <offers>
      <offer id="399" available="true">
        <url>http://www.moy-sayt.ru/catalog/187-p-399.html</url>
        <price>11000</price>
        <currencyId>RUR</currencyId>
        <categoryId>187</categoryId>
        <picture>http://www.moy-sayt.ru/catalog/images/ДУИЛЕР_diski.jpg</picture>
        <name>Bridgestone Dueler H/P Sport</name>
        <description>265-50-19 ЦЕНА УКАЗАНА ЗА 1 КОЛЕСО Bridgestone Dueler H/P Sport- летняя шина для автомобилей 4x4 предназначена для езды на высоких скоростях по трассам и шоссе и входит в первичные комплектации автомобилей Audi Q7, Porsche Cayanne, VW Touareg, обновленной BMW X5 и т.д. Dueler H/P Sport - это великолепная управляемость как на мокрой, так и на сухой дороге. Если Вы хотите приблизить характер Вашего внедорожника к легковому автомобилю и любите динамичную езду, то Вы обязательно оцените шины Dueler H/P Sport, особенно учитывая комфорт и бесшумность, которые они обеспечивают.</description>
      </offer>

      <offer id="402" available="true">
        <url>http://www.moy-sayt.ru/catalog/187-p-402.html</url>
        <price>17500</price>
        <currencyId>RUR</currencyId>
        <categoryId>187</categoryId>
        <picture>http://www.moy-sayt.ru/catalog/images/conticrosscontactuhp_diski.jpg</picture>
        <name>Continental CrossContact UHP</name>
        <description>295-35-21 ЦЕНА УКАЗАНА ЗА 1 КОЛЕСО Continental имеет в своем арсенале шины, специально разработанные для супермощных 4WD автомобилей - шины ContiCrossContact UHP. Их технические характеристики, включая кратчайший тормозной путь и исключительные показатели устойчивости при поворотах на больших скоростях и прекрасная управляемость, делают их незаменимыми для таких требовательных автомобилей 4WD, как: Porsche Cayenne, BMW X5, Range Rover Sport и т. д.</description>
      </offer>

      <offer id="528" available="true">
        <url>http://www.moy-sayt.ru/catalog/187-p-528.html</url>
        <price>5250</price>
        <currencyId>RUR</currencyId>
        <categoryId>187</categoryId>
        <picture>http://www.moy-sayt.ru/catalog/images/DEREZA_diski.jpg</picture>
        <name>dUNLOP DIREZZA DZ101 215/55 R17</name>
        <description>Одна из последних разработок японского завода Dunlop. Шина произведена по усовершенствованной фирменной технологии DIGI-TYRE, получившей название Digital Rolling Simulation II: ещё меньший тормозной путь; ещё большее пятно контакта и, как следствие, великолепная устойчивость на высоких скоростях; потрясающее сцепление с мокрой дорогой; ещё меньшее сопротивление качению - меньший износ и экономия топлива; ещё меньший уровень шума. Это шина, в первую очередь, ориентирована на любителей спортивного типа вождения, но, естественно, её можно рекомендовать абсолютно всем автомобилистам.</description>
      </offer>
      <!-- ... остальные товары ... -->
    </offers>
  </shop>
</yml_catalog>

Важные примечания и рекомендации

  1. Адаптация под вашу версию osCommerce: Скрипт был написан для osCommerce с определенными модификациями. В базовой версии osCommerce 2.3 могут быть некоторые отличия:
  • Структура URL товаров может отличаться (например, product_info.php?products_id=X)
  • Названия полей в базе данных могут незначительно различаться
  • Могут быть другие таблицы или структура хранения данных
  1. Безопасность и оптимизация:
  • Для рабочего магазина рекомендуется добавить кэширование файла (генерировать его не при каждом запросе, а раз в несколько часов)
  • Убедитесь, что ваш сервер поддерживает вызов PHP-скриптов по ссылке
  • Проверьте права доступа к файлу и папкам
  1. Валидация YML:
  • Обязательно проверьте сгенерированный файл через валидатор Яндекс.Маркета
  • Обратите внимание на ограничения по размеру файла и количеству товаров
  1. Дополнительные поля:
  • В спецификации YML есть много полезных полей, которые можно добавить: vendor, model, param, sales_notes и др.
  • Рекомендую изучить официальную документацию YML для расширения функционала
  1. Кодировка:
  • В примере используется кодировка latin1, но для современных магазинов рекомендуется utf-8
  • Убедитесь, что кодировка в заголовке PHP-скрипта, в базе данных и в XML-документе совпадают

Представленный скрипт полностью решает задачу выгрузки товаров из osCommerce на Яндекс.Маркет. Он охватывает все ключевые этапы: подключение к БД, формирование корректной XML-структуры, вывод категорий и товаров. Код снабжен подробными комментариями, что позволяет легко адаптировать его под особенности именно вашего магазина.

Главные преимущества этого решения:

  • Полный контроль над данными и структурой выгрузки
  • Возможность кастомизации и добавления дополнительных полей
  • Четкое соответствие спецификации Яндекс.Маркета
  • Простота понимания и модификации кода

После настройки не забудьте протестировать работу скрипта через валидатор Яндекс и добавить ссылку на него в личном кабинете Яндекс.Маркета. Удачи в продвижении вашего магазина!

Оцените статью
codda