Реализация простого http-сервиса "Просмотр карточки номенклатуры(товара) в браузере"




Принцип обмена данными из 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='\

30 Comments

  1. saa@kuzov.org

    Добавьте еще один гет-метод, который «по ссылке» отдает из базы файл картинки в поток (не в base64, а бинарно).

    И в отображаемую страничку встраивайте картинки именно по этой ссылке.

    Reply
  2. dmitry1975

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

    Reply
  3. saa@kuzov.org

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

    Так же я не уверен, что браузеру будет «хорошо» при большом количестве объемных картинок в формате base64

    Ну и просто полезно такой код по отдаче картинок написать, ИМХО.

    Reply
  4. DO_WHILE_LOOP

    без пагинации на проде не взлетит, с ростом базы начнутся проблемы с выводом GetListNom

    Reply
  5. logarifm

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

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

    Reply
  6. logarifm

    Я к тому виду, что можно же было опубликовать саму 1С завести пользователей для входа или одного общего чтобы не парится и входите будьте здоровы. Лицензия один фиг нужна , что на веб-сервис, что на вход!

    Reply
  7. dmitry1975

    (4) Вы правы, по хорошему конечно нужно разделять информацию на порции..

    У нас это не сильно актуально, потому что количество производимого товара не такое и большое, и новый товар появляется не настолько часто, а если появляется, то скорее всего что-то снимается с производства, поэтому я не стал акцентировать на этом внимание. Но дело даже не в этом.. Данная статья просто реализует пример http-сервиса, который конечно есть куда развивать и дорабатывать:)

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

    Но в любом случае я благодарю вас, за то, что акцентировали внимание на этой важной детали! И обязательно учту это в будущем..

    Reply
  8. logarifm

    Ну и забыл. Вообще можно было без всех маневров использовать ОДАТА 🙂

    Reply
  9. dmitry1975

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

    Reply
  10. dmitry1975

    (5) Спасибо за комментарий!

    Расскажу почему выбран именно http-сервис:

    1. У нас конфигурация «УПП». Для публикации базы, и работы в веб-клиенте необходимы управляемые формы, которые нужно будет для документов, справочников и тому подобное.Часть там есть, но этого недостаточно, потому что реализован большой доп. функционал, которые тоже придется переводить на УФ. На это нужно прилично времени, особенно с учетом того, что времени на это практически нет. Поэтому публикация базы не рассматривается.

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

    3. Возможно я ошибаюсь, но в случае с интерфейсом ODATA, так же через web-интерфейс дается доступ к публикуемым объектам метаданных. Почему нас это не спасет написано выше, но еще раз повторюсь: информация о товаре нужна в одном месте, без лишних телодвижений.

    А теперь чем мне понравился http-сервис?

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

    2. Я реализовал только то, что мне было необходимо, минимальными затратами. Я не сторонник делать универсальные решения, когда нужно решить конкретную задачу! Потому что на универсальное решение затрачивается очень много времени, которого всегда не хватает!

    3. Еще один момент, Http-сервисы в 1С это относительно новая и одна из последних фич платформы 1С, в смысле интеграции с WEB, поэтому просто хотелось разобраться как это работает на реальной задаче. Что и было сделано.

    Еще отвечая на один ваш вопрос: «

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

    У меня ссылка на метод получения информации по элементу, формируется автоматически при выводе, поэтому вводить что-то а в адресную строку не потребуется, и вероятность ошибки существенно снижается 🙂

    Надеюсь, что я смог ответить на ваши вопросы.

    Reply
  11. TitanLuchs

    Хорошая реализация. Пара моментов:

    1. HTML, который генерит 1С при сохранении табличного документа, сильно перегружен лишними стилями и прочими элементами. Будет быстрее работать, если создать шаблон строки таблицы (<tr>) и заполнять этот шаблон данными из 1С, таким образом собирать html всей страницы. Самый идеальный вариант — отправлять в браузер только JSON с данными строки, а саму строку собирать на клиенте яваскриптом, но в этой задаче это конечно, излишне.

    2. Для быстрого отбора неплохо добавить поле поиска. На его обработчик оnchange повесить функцию, которая дернет http-сервис 1С, передав в него еще один параметр — подстроку поиска. По этой подстроке можно выбирать нужную номенклатуру: по наименованию или коду, и формировать список номенклатуры с учетом этого отбора.

    Reply
  12. TitanLuchs

    (6) При прочих равных использование http—сервиса в данной задаче более оптаимльный вариант. Страница загружается значительно быстрее, чем интерфейс 1С, не требуется ввод логинов-паролей, установленная платформа 1С на компьютере не нужна, нагрузка на сервер ниже в разы. И лицензия на веб-сервис в клиент-серверном варианта съедаться не будет ни одна, достаточно лицензии на сервер 1С Предприятия.

    Reply
  13. DO_WHILE_LOOP

    вот как пример оптимизации, посмотрите на скорость загрузки при разбивке по категориям

    https://superdealsae.github.io/category/

    и при варианте полной загрузки каталога

    https://superdealsae.github.io/search

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

    Reply
  14. logarifm

    (10)

    . Поэтому публикация базы не рассм

    У меня была такая же проблематика конфа на ОФ (обычных формах) и постала задача чтобы поставщики могли работать с нашей номенклатурой и для автоматизации процеса делать в ней заявки. Сделал очень просто — ОБРАБОТКА на УФ (управляемой форме) в конфигурации свойство ест-но выставлено использовать ОФ и УФ. И все дал спец. роль и на рабочий стол выделил обработку.

    Reply
  15. dmitry1975

    (11)

    1. Да, это верно подмечено! Содержимое файла, который получается после сохранения табличного документа в формате html, далеко от совершенства :)) Скорее всего попозже я реализую ваш метод.

    2. Про поле «поиска» я думал, но пока для моей задачи это не особо актуально, но в принципе на будущее тоже можно будет сделать. Стандартным поиском по странице работает нормально..

    Спасибо за советы!

    Reply
  16. dmitry1975

    (13) Да видно, что существенно быстрее страничка отображается при разбивке по категориям. Есть куда стремиться.. Спасибо!

    Reply
  17. dmitry1975

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

    Reply
  18. s_vidyakin

    генерить целиком html — так себе решение. У меня есть задумка сделать страницы на vue.js и коннектиться к 1С только за данными. Должны быть абсолютно независимыми представление (html+vue+vuetify) и бэкэнд (1С). Можно отдельно тестить и разрабатывать и то и другое, разными людьми. Было бы идеально, если 1С добавила в платформу поддержку html-макетов для объектов и js-библиотек в секции «Общие объекты». Пока что приходится городить костыли на текстовых макетах. А если вставить в него сжатую js-библиотеку, где несколько килобайт в одну строку, конфигуратор до сих пор падает.

    Reply
  19. TitanLuchs

    (18) Подобные решения в большинстве случаев передаются на поддержку 1Сникам, которые довольно слабо разбираются в vue. Я занимаюсь интеграцией 1С с веб с 2008 года, сделал много проектов на эту тему и всегда предлагаю клиенту варианты: передавать из 1С только JSON и собирать страницу в браузере, или сразу генерить в 1С готовый HTML. Только один выбрал первый вариант, и то потому, что выгружали огромную таблицу порциями, там на готовом HTML браузер начинал подвисать при добавлении новых строк в <table>. Все остальные выбирают генерацию html на стороне 1С, так как это проще и дешевле в сопровождении, но при этом отвечает требованиям по скорости отображения страниц и нагрузки на сервер.

    Reply
  20. dmitry1975

    (20) Я писал выше (пост 10), почему публикация базы в данном случае не подходит.

    Reply
  21. dsdred

    Рад, что статьи пригодились.

    Reply
  22. dmitry1975

    (22) Да, еще раз спасибо за статьи! 🙂

    Прекрасно когда уже есть информация, с которой можно начать изучение 🙂

    Reply
  23. Xershi

    (21) что-то вы лукавите. У вас простой вебсервис, функционал которого на УФ пилится за пол часа. Тут скорее нет опыта на УФ?

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

    Тогда укажите это в начале статьи, а то до коментариев надо дойти же!

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

    Reply
  24. dmitry1975

    (24) Я не понимаю с чего вы взяли, что у меня нет опыта работы на УФ. По большей части, пишу как раз на управляемых формах.

    Но раз вы читаете статью по диагонали не вникая, я не вижу смысла повторяться и писать для вас, почему выбран именно http-сервис. Если интересно, прочитайте внимательно, а если вам просто отметится и написать что-нибудь, то не стесняйтесь! 🙂 только извините, на такие комментарии :

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

    я больше отвечать не буду. Каждый сам для себя решит- полезна ли ему статья или нет.

    Reply
  25. yalex9

    Отличная статья и хоршие комментарии. Спасибо!

    Reply
  26. dmitry1975

    (26) Благодарю за отзыв!

    Reply
  27. Vagner_Hate

    Соглашусь, статья будет полезна тем, кто еще не имеет опыта в создании http-сервисов средствами 1с.

    Reply
  28. dmitry1975

    (28) Благодарю за отзыв.

    Reply
  29. kanyukov

    Привет! можно посмотреть TestDb_HttpService.dt в деле

    Reply
  30. dmitry1975

    (30) Привет! Не совсем понял, это вопрос или утверждение? 🙂

    Reply

Leave a Comment

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