HTML — это просто: Программное формирование HTML документа, содержащего ссылки на объекты БД




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2025-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='\

36 Comments

  1. Saint

    Слишком сложное формирование ссылки объекта. Достаточно пары фукнций ЗначениеВСтрокуВнутр() и ЗначениеИзСтрокиВнутр(). А событие onclick можно обработать проще:

    // Отказ от стандартной обработки клика.
    pEvtObj.returnValue = Ложь;
    
    Если ВРег(pEvtObj.srcElement.tagName) = «A» Тогда
    
    СсылкаТекст = Сред(pEvtObj.srcElement.href, 4);
    Ссылка = ЗначениеИзСтрокиВнутр(СсылкаТекст);
    Если Ссылка.Пустая() Или Ссылка.ПолучитьОбъект() = Неопределено Тогда
    
    Предупреждение(«Выбранный объект был удалён.»,, «Объект удалён»);
    Возврат;
    
    Иначе
    ОткрытьЗначение(Ссылка);
    КонецЕсли;
    
    КонецЕсли;
    

    Показать

    Reply
  2. ll13

    (1) Ваш вариант неработоспособен, у меня была первая мысль сделать именно так как Вы написали, но наступил на грабли.

    ЗначениеВСтрокуВнутр() возвращает строку вида {«#»,e18d5670-dd2f-4528-8897-d3f07ca77f21,37:a1050011d85708ff11dcb5e99d48b4a8} в html тег вы её не запихнете, точнее запихнете, но обратно не получите. Если у Вас есть работоспособная обработка формирующая и обрабатывающая ссылки с помощью

    ЗначениеВСтрокуВнутр() и ЗначениеИзСтрокиВнутр() выложите плиз.

    Reply
  3. Saint

    Отвечаю на удалённое сообщение.

    Во первых я с тобой водку не пил

    Это точно, ибо я спиртное не употребляю. 😀

    По русски понимаешь ? Пишу ещё раз: Если есть работоспособный вариант выложи его.

    Я по-русски понимаю. А ты? Весь смысл обработки я тебе уже написал. Добавлю ещё раз замечание из своего удалённого ответа: сделай

    «v8:» + ЗначениеВСтрокуВнутр(ТвояСсылка)

    и будет тебе счастье.

    Reply
  4. Abadonna

    Тон не сбавите — буду все посты удалять.

    Reply
  5. maxp77

    Мой подход к решению:

    стрOpenOrganization = «OpenInsuranceOrganization»;
    ОрганизацияИд = Строка(МенеджерЗаписи_Пациент_Контакты.Контакт.Владелец.УникальныйИдентификатор());
    ОрганизацияКонтакта = «какое-то описание»;
    /////////////////////////////
    // это кусок HTML
    |   <P id=ОрганизацияКонтакта style=»»DISPLAY:inline»»>«+ОрганизацияКонтакта+»</P>
    ////////////////////////////
    Процедура ПолеHTMLДокументаOnClick(Элемент, pEvtObj, Форма) Экспорт
    
    ЭлементHTML = НайтиЭлемент(pEvtObj.srcElement, «A»);
    Если ЭлементHTML = Неопределено Тогда
    Возврат;
    КонецЕсли;
    
    Если ЭлементHTML.id = «Команда» Тогда
    Попытка
    Форма.ВыполнитьКомандуФормы(ЭлементHTML.pathname, ЭлементHTML.target);
    Исключение
    // в случае неверной или недоступной по правам команды ничего не делаем
    КонецПопытки;
    pEvtObj.returnValue = Ложь;
    
    КонецЕсли;
    
    КонецПроцедуры
    //////////////////////////
    Процедура ВыполнитьКомандуФормы(Команда, Значение) Экспорт
    
    Если Не ЗначениеЗаполнено(МенеджерЗаписи_Пациент_Контакты.Контакт) Тогда
    Возврат;
    КонецЕсли;
    
    Если Команда = «OpenInsuranceOrganization» Тогда
    
    Если Не ПустаяСтрока(Значение) Тогда
    ВыбранныйСправочник = XMLЗначение(Тип(«СправочникСсылка.Страховщики»), Значение);
    ВыбранныйСправочник.ПолучитьФорму(, ЭтаФорма, ЭтотОбъект).Открыть();
    КонецЕсли;
    
    КонецЕсли;
    
    КонецПроцедуры
    
    

    Показать

    Reply
  6. Saint

    (6) У меня нормальный тон. Если человек не понимает шуток — тогда прошу прощения.

    Reply
  7. Abadonna

    (8) Ну вот и славненько. 😉

    Reply
  8. Saint

    (7) Мне кажется, что мой вариант проще и универсальнее. Но это уже дело хозяйское. 😉

    Reply
  9. maxp77

    ///туда

    Строка(___.УникальныйИдентификатор());

    ///оттуда

    XMLЗначение(Тип(«СправочникСсылка.___»), Значение);

    Reply
  10. WKBAPKA

    2(1): + 1 первое что в голову пришло при чтении статьи

    Reply
  11. WKBAPKA

    2(2): строку легко можно преобразовать к удобочитаемому виду… хотя с другой стороны, зачем козе боян, если можно сделать так как в статье )

    Reply
  12. WKBAPKA

    А вот это

    Если СокрЛП(htmlElement.id) <> «» Тогда
    

    можно переписать вот так:

    Если Не ПустаяСтрока(htmlElement.id)  Тогда
    

    лучше смотриться

    но идея интересная, за статью +

    ПЫСЫ: вы уже и поругаться тут успели 😀

    Reply
  13. Shestik

    Люди подскажите, а есть более универсальный вариант обработки onclick… Данный пример заточен под справочники…Конечно труда не составляет переделать его под другие объекты метаданных…Но может есть более универсальный способ…Например, работать, как со справочниками так и с документами…

    Reply
  14. Saint

    (15) Смотри мои 1 и 5 ответы. Изложенный в них способ универсален.

    Reply
  15. Shestik

    (16) Извини не могу разобраться! Приведенный код не работает! Может есть рабочий примерчик!!Буду рад!!

    Reply
  16. Saint

    (17) Приведенный код работает. Делать примерчик времени пока нет.

    Reply
  17. ll13

    (17) Выложил рабочий пример, по методу saint’а, см. статью

    Reply
  18. pavel_pss

    Эх, чувак, где ты был раньше 🙂 . Но все равно полезно

    Reply
  19. Shestik

    (19) Большое спасибо!! Будемс работать!!

    Reply
  20. profes

    [+] За освоение новых технологий V8 🙂

    Reply
  21. Жарков

    Спасибо, буду использовать. Хорошая идея.

    По оформлению статьи — чтобы правильно выводился код, несмотря на наличие HTML-тегов можно использовать тег CODE вместо картинок. Тогда и пользователям легче использовать будет.

    Reply
  22. yku

    (1),(2) и др. Ну что вы велосипед изобретаете? ведь есть же в типовой УТ в форме задачи пользователя:

    » + ?(ТипЗнч(Содержимое) = Тип(«Строка»), СтрЗаменить(Содержимое, Символы.ПС, «»), «» + Строка(Содержимое) + ««) + «</td>

    то бишь они берут просто ЗначениеВСтрокуВнутр() и запихивают в id, где он прекрасно сохраняется :).

    Reply
  23. Saint

    (24) А у тебя проблемы с изобретением велосипедов? Описанный тобой способ является не более чем ещё одним способом решения указанного вопроса и не сильно отличается от предложенного мной варианта. К тому же мной этот вариант был придуман ещё тогда, когда в типовой об этом, скорее всего, нервно курили. Так что тут ещё вопрос, кто изобретает велосипед.

    Reply
  24. yku

    (25) ого — немного ошарашен тоном. Предложенный вами вариант (в том виде, в каком он здесь опубликован) все-таки не работоспособен из-за наличия символа «#» в получаемой строке. И хоть это ограничение обходится за десять секунд, но обходить-то его надо. Так что вариант из типовой — легче. А существенных отличий действительно нет.

    О «велосипеде» было к слову. Сожалею, что это вас «задело».

    Reply
  25. ll13

    (26) Оба варианта, которые опубликованы в статье полностью работоспособны, 2-ой вариант который предложил saint наиболее простой и универсальный. Специально замечу что символ «#» нисколько не мешает ему работать 😉

    Reply
  26. Saint

    (26) Меня это не задело. Просто не нужно утверждать, что типовая — это круто и только там может быть правильное решение. И прежде чем утверждать, что вариант не рабочий, это не мешало бы для начала проверить. МОЙ вариант у меня работает уже года эдак 4. Почему мне не мешает символ «#»?

    Reply
  27. yku

    (27) хм. а у меня мешает :(. Нет, серьезно. 1с стопорится при получении значения href. Пропадают все символы до #. Причем, если до последнего символа «#». То есть, если завернуть во всякие структуры, массивы и проч — теряется. может, от версии IE зависит?

    Reply
  28. ll13

    (29) Всё дело в волшебных пузырьках 😀 , а точнее в префиксе «v8:»

    Reply
  29. yku

    (30) да ставлю я его. проверил на другом компе — нормально. что за магия? или просто спать пора?

    Reply
  30. Saint

    (31) Фиг его знает. Вариант нормально работал на IE, начиная с версии 6. Тем более что у меня используется не простой HTML, а преобразование XSL. И проблем не возникало никогда. Так что спать! 😀

    Reply
  31. O-Planet

    Это все замечательно… Но вот реально что хочется, так это работать внутри html с объектами 1С, как с объектами именно, т.е. обращаться к их реквизитам, изменять их при необходимости и т.д. На javascript… Эх… 🙁

    Reply
  32. O-Planet

    Поясню… Передаю, скажем, список в html, там сортирую, и он в 1С соотвественно отсортирован…

    Reply
  33. Saint

    (34) Мда… А что мешает передать уже отсортированный средствами 1С список? HTML как бы немного не предназначен для таких операций.

    Reply
  34. Muhin555

    А нет ли примерчика, где бы обрабатывались Checkbox-ы в теле HTML документа и значения их передавались бы в 1С????

    Reply
  35. PerlAmutor

    удалено.

    Промазал с темой.

    Reply
  36. 🅵🅾️🆇

    (1) Прошу прощения за некропостинг, но вот кратенькая адаптация под УФ

    &НаКлиенте
    Процедура СписокПрисутствующихСотрудниковПриНажатии(Элемент, ДанныеСобытия, СтандартнаяОбработка)
    Если ДанныеСобытия.Anchor = Неопределено Или ВРег(ДанныеСобытия.Anchor.tagName) <> «A» Тогда Возврат КонецЕсли;
    СтандартнаяОбработка = Ложь;
    Ссылка = ПолучитьСсылкуСотрудникаИзСтрокиВнутр(Сред(ДанныеСобытия.Href, 4));
    Если Ссылка.Пустая() Тогда Сообщить(«Ошибка получения ссылки сотрудника.»); Возврат КонецЕсли;
    ОткрытьЗначение(Ссылка);
    КонецПроцедуры // СписокПрисутствующихСотрудниковПриНажатии()
    
    &НаСервереБезКонтекста
    Функция ПолучитьСсылкуСотрудникаИзСтрокиВнутр(Строка)
    Попытка
    Ссылка = ЗначениеИзСтрокиВнутр(Строка);
    Если Ссылка.ПолучитьОбъект() = Неопределено Тогда
    Возврат ПредопределенноеЗначение(«Справочник.Сотрудники.ПустаяСсылка»);
    Иначе
    Возврат Ссылка;
    КонецЕсли;
    Исключение
    Возврат ПредопределенноеЗначение(«Справочник.Сотрудники.ПустаяСсылка»);
    КонецПопытки;
    КонецФункции // ПолучитьСсылкуСотрудникаИзСтрокиВнутр()
    

    Показать

    Reply

Leave a Comment

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