Итак, нам необходим интернет магазин под Joomla, для данной статьи выбран JoomShopping, т.к. автор считает его наиболее перспективным, в отличие от все более отстающего VirtueMart-а. Но, в принципе, технология для других магазинов отличается лишь структурой БД, и никаких препятствий для её использования нет.
Если у Вас нет интернет-магазина, но вы хотите на практике опробовать обмен, инструкция по его созданию на хостингах timeweb и radiushost приложена к данной статье. Будем считать, что магазин уже у нас есть.
Нам нужно установить ODBC драйвер для соединения с базой данных. Для его установки нужно скачать и установить MicrosoftVisualC++ 2010 RedistributablePackage (x86) с http://www.microsoft.com/en-us/download/confirmation.aspx?id=5555, скачать и установить MySQL Connector/ODBC 5.3.4 c http://dev.mysql.com/downloads/connector/odbc/
Можно приступать к разработке. При установке соединения с базой данных важно установить кодовую страницу 1251, для нормального отображения русских символов. Для этого в строке соединения указываем «STMT=SET CHARACTER SET CP1251». В итоге подключение к БД будет выглядеть примерно так:
СтрПодключения = "DRIVER={MySQL ODBC 5.3 Unicode Driver};";
СтрПодключения = СтрПодключения+"SERVER="+Хост+";";
СтрПодключения = СтрПодключения+"Database="+ИмяБазы+";";
СтрПодключения = СтрПодключения+"Uid="+Логин+";PWD="+Пароль+";Option=3;STMT=SET CHARACTER SET CP1251";
Соединение=Новый COMОбъект("ADODB.Connection");
Соединение.Open(СтрПодключения);
При составлении запросов к БД есть один немаловажный нюанс. Поля, содержащие некоторые нехорошие символы, нужно брать в кавычки. Таких полей будет большинство, поэтому лучше брать в кавычки все поля. Только кавычки эти непростые, а вот такие `<имяполя>`. Код символа таких кавычек отличается от стандартного, это необходимо учитывать. Также нужно понимать, что у всех таблиц вашей БД есть префикс, который нужно добавлять слева к имени таблицы. Пример запроса:
ТекстЗапроса="DELETE FROM "+Префикс+"jshopping_categories";
Соединение.Execute(ТекстЗапроса);
Неплохо было бы оптимизировать наши запросы к БД. Не только с точки зрения самого запроса, но и с точки зрения количества передаваемых на хост данных. Например, синхронизацию товаров мы производим по коду. Тогда схема, когда мы отправляем для каждой номенклатурной позиции запрос «update», либо «insert» , будет неоптимальной. Причем для определения, какой из запросов мы будем делать, нам придется предварительно прочитать все коды из таблицы товаров. Как раз для такого случая подходит синтаксис «INS ERT ON DUPLICATE KEY UPDATE”, который позволяет обновить значения полей, если строка с таким ключом уже существует, либо, если нам не нужно ничего делать с уже существующими в БД строками «INS ERT IGNORE». В итоге запрос на обновление всей таблицы за один запрос будет выглядеть следующим образом «INS ERT IN TO <таблица> (<поле1>,..,<полеn>)VALUES (<Знач1>,...,<Значn>),...,(<Знач1>,...,<Значn>) ON DUPLICATE KEY UPDATE <поле1>=VALUES(<Знач1>),...,<полеn>=VALUES(<Значn>)». Такие запросы будут работать наиболее эффективно, правда при этом необходимо следить за тем, чтобы длина строки текста запроса не превысила максимум, установленный для базы. Пример формирования запроса:
Запрос=Новый Запрос;
Запрос.Текст="ВЫБРАТЬ
| КатегорииПапок.Папка КАК ПапкаНоменклатуры,
| КатегорииПапок.КодКатегории
|ПОМЕСТИТЬ ВТ_КатегорииПапок
|ИЗ
| &КатегорииПапок КАК КатегорииПапок
|ГДЕ
| КатегорииПапок.Выгружать
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Товары.Ссылка КАК Номенклатура,
| ВТ_КатегорииПапок.КодКатегории КАК КодКатегории,
| Товары.Наименование КАК Наименование,
| Товары.Код КАК Код,
| ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена,
| ЕСТЬNULL(ТоварыНаСкладахОстатки.КоличествоОстаток, 0) - ЕСТЬNULL(ТоварыВРезервеНаСкладахОстатки.КоличествоОстаток, 0) КАК Количество
|ИЗ
| ВТ_КатегорииПапок КАК ВТ_КатегорииПапок
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Товары
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| ,
| ТипЦен = &ТипЦен
| И ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК ЦеныНоменклатурыСрезПоследних
| ПО Товары.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
| ,
| Качество = ЗНАЧЕНИЕ(Справочник.Качество.Новый)
| И ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК ТоварыНаСкладахОстатки
| ПО Товары.Ссылка = ТоварыНаСкладахОстатки.Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(, ХарактеристикаНоменклатуры = ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)) КАК ТоварыВРезервеНаСкладахОстатки
| ПО Товары.Ссылка = ТоварыВРезервеНаСкладахОстатки.Номенклатура
| ПО ВТ_КатегорииПапок.ПапкаНоменклатуры = Товары.Родитель
|ИТОГИ
| МИНИМУМ(Наименование),
| МИНИМУМ(Код),
| МИНИМУМ(Цена),
| МИНИМУМ(Количество)
|ПО
| Номенклатура";
Запрос.УстановитьПараметр("КатегорииПапок",КатегорииПапок);
Запрос.УстановитьПараметр("ТипЦен",Цена);
Результат=Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
ТекстЗапросаНоменклатура="INSERT "+?(ОбновлятьСтаруюНоменклатуру,"","IGNORE ")+"IN TO "+Префикс
+"jshopping_products (`product_id`,`product_date_added`,`date_modify`,`product_publish`,`name_ru-RU`,`description_ru-RU`,`short_description_ru-RU`,`product_price`,`product_quantity`) VALUES ";
ПустойЗапрос=Истина;
ТекстЗапросаКатегорииНоменклатуры="INSERT IGNORE IN TO "+Префикс
+"jshopping_products_to_categories (`product_id`,`category_id`) VALUES ";
ВыборкаНоменклатура=Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Пока ВыборкаНоменклатура.Следующий() Цикл
ТекстЗапросаНоменклатура=ТекстЗапросаНоменклатура+?(ПустойЗапрос,"",",")+"("
+ВыборкаНоменклатура.Код+",'"+Формат(ТекущаяДата(),"ДФ='yyyy-MM-dd HH:mm:ss'")
+"','"+Формат(ТекущаяДата(),"ДФ='yyyy-MM-dd HH:mm:ss'")
+"',1,"""+СтрЗаменить(СтрЗаменить(ВыборкаНоменклатура.Наименование,Символы.ПС,"\n"),Символы.Таб,"\t")
+""","""+СтрЗаменить(СтрЗаменить(ВыборкаНоменклатура.Наименование,Символы.ПС,"\n"),Символы.Таб,"\t")
+""","""+СтрЗаменить(СтрЗаменить(ВыборкаНоменклатура.Наименование,Символы.ПС,"\n"),Символы.Таб,"\t")
+""","+Формат(ВыборкаНоменклатура.Цена,"ЧДЦ=2; ЧРД=.; ЧН=0.00; ЧГ=0")
+","+Формат(ВыборкаНоменклатура.Количество,"ЧДЦ=2; ЧРД=.; ЧН=0.00; ЧГ=0")+")";
Выборка=ВыборкаНоменклатура.Выбрать();
Пока Выборка.Следующий() Цикл
ТекстЗапросаКатегорииНоменклатуры=ТекстЗапросаКатегорииНоменклатуры+?(ПустойЗапрос,"",",")+"("
+Выборка.Код+","+Выборка.КодКатегории+")";
ПустойЗапрос=Ложь;
КонецЦикла;
КонецЦикла;
КонецЕсли;
Если Не ПустойЗапрос Тогда
Если ОбновлятьСтаруюНоменклатуру Тогда
ТекстЗапросаНоменклатура=ТекстЗапросаНоменклатура+" ON DUPLICATE KEY UPDATE `product_publish`=1,`date_modify`=VALUES(`date_modify`),`name_ru-RU`=VALUES(`name_ru-RU`),`description_ru-RU`=VALUES(`description_ru-RU`),`short_description_ru-RU`=VALUES(`short_description_ru-RU`),`product_price`=VALUES(`product_price`),`product_quantity`=VALUES(`product_quantity`)";
КонецЕсли;
Соединение.Execute(ТекстЗапросаНоменклатура);
Соединение.Execute(ТекстЗапросаКатегорииНоменклатуры);
КонецЕсли;
К статье приложена обработка для выгрузки товаров в интернет-магазин JoomShopping из 1С УТ 10.3 или КА 1.1. Данная обработка также будет работать в конфигурациях, которые используют структуру хранения остатков и цен номенклатуры, аналогичную УТ. Поскольку обработка предназначена для демонстрации работы с интернет-магазином как с базой данных, она имеет ряд ограничений, например, не выгружаются картинки. Ограничения и инструкция по использованию данной обработки находится в приложении к статье.
Структуру таблиц и полей БД интернет-магазина можно определить при помощи phpMyAdmin в панели управления сайта. К статье приложена структура БД магазина на JoomShopping 4.12.3