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




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2026-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 не будет опубликован. Обязательные поля помечены *