Для демки нужно какое-то время, обязательно подготовлю.
Расскажу технологию.
Начнем с того, что договоримся, что все данные создаются в 1C, OpenCart служит только движком для отображения этих данных, администрирование товаров в OpenCart категорически не желательно.
Данные в 1С и OpenCart надо как-то синхронизировать по какому-то единому ключу. В OpenCart уникальный ключ это product_id, но т.к. данные изначально берутся из 1С, то ключ для синхронизации должен браться из него. Как вариант это может быть код справочника, плюс этого варианта - компактность, как правило длина кода 8-10 символов, минус - при удалении элемента справочника из 1С, эту же операцию мы не сможем проделать в OpenCart, результатом будет накопление в базе ненужных данных, которые должны быть удалены. Поэтому единственно правильным решением - это использовать GUID. Плюсов в использовании глобального уникального id в том, что во-первых можно изменять любые данные в справочниках, включая код и это никак не повлияет на искажение или неразбериху в базе OpenCart, во-вторых при удалении элемента справочника в 1С (обязательное использование плана обмена), мы точно так же сможем удалить этот элемент и в OpenCart, минус - в избыточности, длина GUID - 36 символов.
Перейдем к формату данных для обмена.
Отказываемся от использования XML, за его прожорливость. Все очень просто, пишем в текстовый файл построчно, одна запись - одна строка, поля отделяем разделителем, как правило это запятая (,), строки заключаем в кавычки ("), числа нет. В PHP есть функция fgetcsv(), которую мы и будем использовать для загрузки.
В 1С собираем нужные нам данные используя план обмена, либо полная выгрузка всех данных. Первая строка файла обмена - служебная, туда можно включить, например, придуманный нами протокол обмена, его версию, тип выгрузки и т.п. При загрузке мы будем анализировать эту строку, для дальнейших действий, например, если версия загрузчика не совпадет с версией выгрузки (случайно подвернулся старый файлик обмена), то отказываемся от загрузки, если это полная выгрузка, то предварительно в OpenCart нужно почистить все таблицы, ну и т.п.
В один файл будем писать данные по нескольким таблицам, для этого будем включать строку с ключевой фразой, например, для товаров - Products, для производителей - Manufacturers.
Важна последовательность размещения таблиц, т.е. данные в которые включены ссылки на другие таблицы, должны идти позже. У меня эта последовательность такая НоменклатурныеГрупп (в opencart категории),ЗаводыИзготовители, ВидыХарактеристик, Номенклатура, ХарактеристикиНоменклатуры, ну и так далее.
Вот пример записи из 1С данных по товарам:
//...
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Количество() > 0 Тогда
Файл.ЗаписатьСтроку("Products");
Пока Выборка.Следующий() Цикл
GUID = Выборка.Ссылка.УникальныйИдентификатор();
//...
Файл.ЗаписатьСтроку("""" + GUID + """,""" + Наименование + """,""" + Код + """,""" + ИмяКартинки + """,""" + GUID_ЗаводИзготовитель + """,""" + GUID_НоменклатурнаяГруппа + """,""" + GUID_ВидХарактеристикиНоменклатуры + """,""" + ДатаДоступности + """," + Статус + "," + Цена + "," + Остаток + "," + СтатусЗапаса);
КонецЦикла;
КонецЕсли;
Загрузка в OpenCart.
Предварительно нужно создать несколько таблиц для синхронизации справочников, как было описано выше.
Например, для таблицы товаров:
CREATE TABLE IF NOT EXISTS `oc_1c_product` (
`guid` varchar(36) COLLATE ascii_general_ci NOT NULL,
`product_id` int(11) NOT NULL,
PRIMARY KEY (`guid`),
KEY `product_id` (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=ascii COLLATE=ascii_general_ci;
Вот пример функции для получения данных по товару по имеющемуся у нас GUID:
function getProductByGuid($guid) {
$data = false;
$result = $this->db->query("SELECT p.*, pd.* FROM " . DB_PREFIX . "1c_product cp
LEFT JOIN " . DB_PREFIX . "product p ON (cp.product_id = p.product_id)
LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
WHERE cp.guid = '" . $this->db->escape($guid) . "' AND pd.language_id = '" . (int)$this->language_id . "'");
if ($result->num_rows > 0) {
$data = $result->row;
}
return $data;
}