Веб-сервисы, что они и как их применить в реальных условиях




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

28 Comments

  1. awk

    Причины почему поставил минус.

    1. Непонятно, что и зачем выгружаем.

    2. Запросы в цикле.

    3. Смысл статьи непонятен.

    3.1 Почему веб сервис лучше файлов — из статьи непонятно.

    3.2 Зачем такие сложности если есть планы обмена — то же непонятно из статьи.

    4. Смешаны гетерогенная среда с гомогенной.

    Reply
  2. DitriX

    (1)читаем статью 🙂

    1.

    Ну пожалуй следует начать с того, как мы выгружали номенклатуру и ее описание, изначально мы просто раз в какой то период – выгружали файлик xml на ftp, этот период выбирал кто угодно, сайт его автоматом подхватывал и обновлял. Но, так как мы легких путей не ищем, было принято решение добавить в номенклатуру реквизит ДатаИзменения, и тогда выгружалась только та номенклатура, которая была изменена начиная с указанного периода.

    И таких примеров много, по сути всю статью надо копировать.

    2.Эммм, что то я не понял вопроса, где вам там цикл не пришелся по вкусу?

    Я таким образом решил проблему создания двух отдельных функций.

    Если вы про цикл по складам, то это было обусловленно тем, что если один раз слать общий запрос — и вытаскивать результат, то массив данных был оооочень большой. И сайт мог не успеть быстро обработать все данные. Поэтому были разделены склады запросом. Можно было бы выполнить общий запрос, поместить в ВТ и работать с ней, или выгрузить в ТЗ, добавить индексы и там уже отбирать, но результат тестирования показал, что время затраченное на такой цикл, в сравнении с другими подходами, составлял менее 1%, поэтому, для удобства редактирования, был оставлен этот подход.

    3. Из статьи этого и не должно быть понятно. Тут каждый делает так, как ему по душе, я привел аналог обмена без файлов.

    3.1 Кроме этого, один из главных плюсов — мгновенный обмен данными любого количества. Мне интересно как вы построите обмен данными в онлайне при помощи файлов?

    3.2 Да ну, настройте-ка план обмена между двумя абсолютно отличающимися базами, причем эти базы не есть дочерние, ну и подключите туда несколько ИМ, и это все в режиме онлайна. Если вы это сделаете — я вам сделаю низкий поклон.

    Однако, объем данных значительный (около 100 000 позиций + размеры и прочее), в базах работает около 100 пользователей.

    4. Это и была цель, показать — как можно с помощью веб сервисов решить проблему объединения кучи различных баз (1С — база ИМ), а так же преимущества, при объединении сходных баз (1С — 1С)

    Надеюсь — я ответил на ваши вопросы, и вы можете изменить свое мнение о моей статье 🙂

    Reply
  3. awk

    (2)

    1. «И таких примеров много..» И разбросаны по тексту, что не понять к чему что и почему.

    2. «цикл не пришелся по вкусу?» Запрос не должен быть в цикле — точка. Это стандарт. В твоем случае делается запрос и обход выборки по группировкам.

    Тут каждый делает так, как ему по душе,

    Я обычно исходя из задач.

    один из главных плюсов — мгновенный обмен данными любого количества

    Не верю. Телепорт что ли?

    Мне интересно как вы построите обмен данными в онлайне при помощи файлов?

    Что есть онлайн?

    настройте-ка план обмена между двумя абсолютно отличающимися базами

    УТ и БП или ЗУП и БП подойдут? Если подойдут, жду поклона 😀

    Однако, объем данных значительный (около 100 000 позиций + размеры и прочее), в базах работает около 100 пользователей.

    Это к чему?

    Это и была цель, показать — как можно…

    А получилась каша.

    Да я и не сильно против. Сделать оглавление, подчистить код и будет вполне плюс.

    Reply
  4. p1l1gr1m

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

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

    Но что касается части работы с соап — однозначный плюс.

    Reply
  5. coder1cv8

    Автор, Вы не обижайтесь, правильно выше говорят, Ваши решения очень …мягко говоря… спорные. Это не пример красивого решения, это набор каких-то личных велосипедов с квадратными колесами местами. Нет планов обмена, методология хромает на обе ноги, вся суть и привлекательность SOAP сервисов в объектном подходе, а Вы данные XML-строкой передаете (если я правильно понял).

    Reply
  6. bforce

    Интересно, народ вообще в коде разбирался?

    Где там запрос в цикле? Цикл состоит из 2-х итераций, причем на каждой из них выполняется своя ветка. Такое ощущение, что просмотрели статью бегло.

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

    ИМХО, в рамках этой статьи можно обойтись без плана обмена. Сама идея понятна и проста без всяких излишеств.

    Reply
  7. awk

    (6) bforce,

    Где там запрос в цикле?

    /Для случая ИМ1 мы выполняем отдельный запрос и отправку для каждого склада
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    Попытка
    //Пытаемся получить хмл строку для данного склада
    хмл = ПолучитьХМЛ(ВыборкаДетальныеЗаписи.Ссылка, Номер);
    
    …..
    
    //Собственно сама функция для получения хмл
    Функция ПолучитьХМЛ(Склад,Номер)
    //тут для каждого случая, мы создаем свою таблицу
    Если Номер = 0 Тогда
    Запрос = Новый Запрос(«ВЫБРАТЬ РАЗРЕШЕННЫЕ
    
    

    Показать

    ощущение, что просмотрели статью бегло.
    Reply
  8. DitriX

    (3) 1. Чухча не писатель, так что звиняйте.

    2. Спасибо что столько внимания уделили моему правописанию.

    Не верю. Телепорт что ли?

    Нет, но нет необходимости подключать какие то отладчики ожидания.

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

    Однако, вы не получите ответ от сервера, например «Код номенклатуры не найден». А он просто проглотит ваш файл и не подавится. Потом в приемнике — вы может и буду видеть ошибку, но не в базе отправителе.

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

    Что есть онлайн?

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

    УТ и БП или ЗУП и БП подойдут? Если подойдут, жду поклона 😀

    Не вырывайте из контекста, я сказал:

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

    Однако, объем данных значительный (около 100 000 позиций + размеры и прочее), в базах работает около 100 пользователей.

    И тут основную роль играет значительный объем данных и явная неоднородность участников. Т.е. эти планы вы уже не примените к сайту.

    А получилась каша.

    «Мало ли что я там варила» (из анекдота)

    Reply
  9. DitriX

    (4) такой подход был выбран из за удобства чтения/изменения/доработки.

    Может это и велосипед, но правил он никаких не нарушает — я всегда вижу очередь которая стоит к сайту, я могу ее быстро редактировать, я могу применить стандартные обработки для работы с регистрами сведений — а вот для планов обмена таких мало, если вообще есть, а свои писать — кто платить будет 🙂

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

    Этот вариант более гибкий, в противном случае — на каждый сайт и на каждую функцию — необходимо будет создавать свои пакеты. А это весьма раздует код.

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

    Reply
  10. DitriX

    Внимание! Мораль статьи такова — не делайте запросы в цикле. 🙂

    Если честно, то интересные люди откликнулись на статью. И хотелось бы узнать ваши подходы к решению аналогичных ситуаций, и проблем, с которыми вы столкнулись.

    Вот я, например, не люблю планы обмена, как то не сложилось. Я всегда стараюсь работать в онлайне.

    Из-за обменов очень много проблем, + эти файлы выгружать, иногда по 300 метров, это ужас.

    И мне очень сильно не хватало ответа от сервера, что он успешно загрузил данные и т.д.

    Да, SOAP я использую как контейнер для передачи данных, хотя иногда и по назначению, но это реже, но таким образом он решает все мои проблемы, а чего еще нужно? 🙂

    У нас вот есть в базе Чат, и есть несколько франчей, чо своими базами, и есть партнеры, которые вообще ни как не пересекаются с нами по 1С. Но вот чат — работает по SOAP и всегда в режиме онлайна.

    Согласитесь, реализовать такое файлами — убожество.

    Reply
  11. comol

    «Уж сколько раз твердили миру»… не для обмена остатками каждые 30 секунд web сервисы предназначены… Если хотите действительно красиво и «полный online» это нужно делать по-другому… не файлами конечно, слишком просто, но и не web сервисами.. которые по сути представляют RPC через Web интерфейс. А вы тут «гвозди микроскопом»…

    Reply
  12. awk

    (8)

    Скорость:

    Нет, но нет необходимости подключать какие то отладчики ожидания.

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

    Однако, вы не получите ответ от сервера, например «Код номенклатуры не найден». А он просто проглотит ваш файл и не подавится. Потом в приемнике — вы может и буду видеть ошибку, но не в базе отправителе.

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

    1. Обработчик ожидания — это не проблема для алгоритма, т.к. O(x) = C. —

    2. Ответ я не получу только когда не предусмотрю ответ. То же не проблема. —

    Вид транспорта влияет на скорость обмена, не так сильно как выборка из базы данных (при достаточно большом объеме передаваемых данных).

    Онлайн:

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

    Что бы в базах была актуальная информация применяется механизм распределенных транзакций.

    Планы обмена:

    И тут основную роль играет значительный объем данных и явная неоднородность участников. Т.е. эти планы вы уже не примените к сайту.

    План обмена занимается регистрацией изменений. Что регистрировать — дело ваше. Скорость костыля(даже хорошего) будет <= скорости встроенного механизма плана обмена.

    Reply
  13. awk

    (10)

    интересные люди откликнулись на статью

    Ибо тема интересная. 99% статей на сайте как сделать яйцам -вид сбоку.

    хотелось бы узнать ваши подходы к решению аналогичных ситуаций, и проблем

    1. Выявление необходимой информации для обмена

    2. Классификация информации по критичности задержек при передачи

    3. Оценка объема передаваемой информации

    4. Выбор метода передачи

    5. Выбор транспорта для передачи

    6. Реализация модели

    7. Если модель достаточна — завершаем иначе переход к 4 пункту.

    Reply
  14. DitriX

    (11) буду признателен за описание вашего решения.

    (12)

    План обмена занимается регистрацией изменений. Что регистрировать — дело ваше. Скорость костыля(даже хорошего) будет <= скорости встроенного механизма плана обмена.

    Согласен, не подумал, спасибо за совет.

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

    Reply
  15. DitriX

    (13) из вашей практики — когда и почему вы выбрали именно этот подход?

    Очень интересно, прям сгораю от нетерпения узнать 🙂 Буду признателен за развернутый ответ.

    Reply
  16. awk

    (15)

    Почему?

    Потому, что был стабильный канал связи. И руководство шло на признание отсутствия связи форс-мажором. Без этого вся прелесть SOAP теряется.

    Когда?

    1. Когда надо было реализовать распределенные транзакции. (самый простой способ)

    2. Когда нужно было сделать API для управления системой.

    3. Когда нужно было сделать API для доступа к данным из вне. (REST предпочтительней)

    Reply
  17. DitriX

    (16) И на том спасибо 🙂

    Reply
  18. comol

    (14) План обмена, прямая запись в БД, двустороняя репликация, сверка изменений. Если уж заморочиться то так.

    Reply
  19. comol

    (16) awk, Респект. Ведь есть же оказывается люди которые понимают что такое SOAP и зачем оно нужно 🙂

    Reply
  20. xzorkiix

    А где XDTO пакеты? Что за?

    Reply
  21. DitriX

    (20) прочитайте внимательней комментарии к теме, тут было решение без оных.

    При явной необходимости — не проблема добавить, но это уже другая тема

    Reply
  22. fr.myha

    Много разных споров, но спасибо за эту статью. Для меня тема актуальна.

    Reply
  23. Кебабыч

    А мне статья понравилась. А отправка XDTO пакетами может быть и оправданной — у меня была проблема, когда soap запрос сформированный 1С корректно не парсировался на другом конце, а при отправке пакетами я его могу скорректировать, что автор в статье и сделал, выбросив «мусор» из xml.

    Reply
  24. DitriX

    (23) кстати говоря — если на обратной стороне 1с, и все типы колонок простые, то можно в приемнике прописать что бы он приводил хмл к начальному виду и десериализовал. Таким образом мы получаем что то вроде архиватора. Кроме этого — так можно передавать и файл. Ну например у вас есть оооочень большой хмл, метров на 100, вы его архивируете и передаете через соап, на другой стороне — разархивируете и парсите. Или десириализуете.

    Жаль что 1с не может заархивировать строку, без создания файла.

    Reply
  25. tarikss

    Статья нормальная, мне пришлась по вкусу!

    Reply
  26. logarifm

    На основе данной статьи и при помощи автора удалось создать мобильную торговлю, которая какраз-таки использует обмен через веб-сервис!!!

    Данные реально быстро уходят и достаточно Сериализовать и десириализовать.

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

    К комменту (1) и т.д. по тексту, ну для начала надо разобраться в теме, а не искать изъяны в коде.

    Еще раз автору спасибо. Из своего хочу добавить, что удалось еще оптимизировать пакеты используя элементарное ХранилищеЗначений с сжатием максимальным 9.

    Reply
  27. DitriX

    (26) спасибо за отзыв, но Хранилище — работает только в режиме 1С-1С, а в статье приведен пример обмена 1С-веб сайт.

    Reply
  28. Manticor

    DitriX, скажите, а если делать реализацию двустороннего обмена при помощи сервисов — много кода нужно для этого добавлять???

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *