Прием конвертации, который позволит решить много задач




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

44 Comments

  1. Филин

    Со всеми примерами еще подробно не разобрался, но по первому есть вопросы.

    Прием с выгрузкой «фальшивого» объекта — крутой и иногда очень сильно спасает, но тут, кажется, можно было сделать проще. Я в похожей ситуации создавал «СписокЗначений», заполнял его значениями с представлениями, имена которых совпадают с именами полей приемника, а потом передавал в ПКО как «ВходящиеДанные». Табличные части передаются как ТаблицыЗначений. При этом получается, что не надо определять в каждом ПКС переменную «Значение», она сама из входящих данных подтянется. ПКО и ПКС выглядят более аккуратно что-ли, ну и по полной используются механизмы, заложенные в КД

    Получается что-то вроде такого:

    ПВД:

     ..тут может быть какой-то цикл…
    
    данныеДокумента = создатьОбъект(«СписокЗначений»);
    данныеДокумента.добавитьЗначение(1,»НомерДок»);
    данныеДокумента.добавитьЗначение(«Перенос данных»,»Комментарий»);
    
    тчДокумента = создатьОбъект(«ТаблицаЗначений»);
    тчДокумента.новаяКолонка(«Сумма»);
    тчДокумента.новаяСтрока();
    тчДокумента.сумма = 100;
    
    данныеДокумента.добавитьЗначение(тчДокумента, «Платежи»);
    
    выгрузитьПоПравилу(«заглушка»,,данныеДокумента,,»Платежка»);
    
    …конец цикла…

    Показать

    В ПКО у реквизитов шапки и у ПКГС табличной части ставим флаг «получить из входящих данных». Бонус: в ПКС полей табличной части не надо ничего писать или ставить какие-то галки, все само схватится

    Reply ↓
  2. LexSeIch

    Мир этому дому!

    Конвертация — как шаманство — есть инструмент и правила, а все остальное свобода творчества. Судя по статье — это результат практического использования. Это всегда плюс.

    Reply ↓
  3. Азбука Морзе

    После того как познакомился с XDTO-серилизацией конфигурацию «Конвертация данных» вспоминаю как страшный сон. Автор молодец. На конкретном примере показал убогость и неестественность правил и приемов КД при обмене данными между разнородными системами. За это и плюсую.

    Reply ↓
  4. stanru1

    (3) особенно в 7.7 XDTO сериализация рулит 🙂

    на практике перенос (планирование — разработка — тестирование — эксплуатация) из конфигурации 77 в 82 с помощью КД выполняется в несколько раз быстрее, чем альтернативные варианты.

    Reply ↓
  5. Istur

    (3) xotr, раз такой крутой механизм для тебя, то почему нет ни одной твоей статьи про XDTO-сериализацию?

    Reply ↓
  6. AlexO

    (5) Istur,

    так одно в страшном сне, другое — видимо, в прекрасном сне 🙂

    Reply ↓
  7. Азбука Морзе

    (5) xotr не писатель, xotr читатель:)

    п.с. В соседней ветке про XDTO целый цикл статей замутили, желающие могут ознакомится.

    Reply ↓
  8. Yashazz

    Да, это идея, полезная на практике. Ещё в 2008-м пользовался точно таким подходом, разве что между двумя восьмёрочными конфами. Спасибо автору, что подробно всё разжевали и показал, мне в своё время недосуг было.

    Reply ↓
  9. ARL

    Автор заслуживает громадное уважение за то, что самостоятельно разобрался с системой КД, т.к описание КД оставляет желать лучшего (мягко говоря). Но сейчас для программистов появился громадный помощник — курсы Гилева. Все подобные задачи на курсах выполняются в качестве домашнего задания, от «шаманства» ничего не остается.

    (3) xotr, «На конкретном примере показал убогость и неестественность правил и приемов КД при обмене данными между разнородными системами.»

    На самом деле, это вопрос компетенции. Если разобраться с КД — то никакой убогости, вполне достойная и работоспособная система.

    Reply ↓
  10. Stepan_1c

    спасибо за статью) на пару дней пораньше бы еще лучше было) эээх)

    Reply ↓
  11. DoctorRoza

    Хорошая статья, очень нужная информация! Плюс однозначно! 🙂

    Reply ↓
  12. KliMich

    Спасибо! Наглядные и показательные примеры, когда надо «приготовить из ничего…»

    Reply ↓
  13. IgorXml

    Спасибо. Наглядно сделал.

    Reply ↓
  14. OVladius

    Где вы раньше были? Всех сотрудников с 7-ки руками фигачили 🙁

    Reply ↓
  15. fomix

    (3) xotr, Интересно как в XDTO можно решить задачи по конвертации одного объекта в другой, получения из одного объекта двух и более, а также наоборот, настроить поиск и прочие фичи. Сдается мне у вас есть опыт тривиального обмена через XDTO между типовыми конфами в общем виде. Не помню, чтобы при использовании XDTO, можно было бы вмешаться в процесс формирования итогового файла выгрузки.

    Reply ↓
  16. Boroda

    Отличная статья! Помогла разобраться в некоторых вопросах, где раньше тупил. Спасибо автору!

    Reply ↓
  17. sa1m0nn

    Спасибо за статью, нормально написано, хоть и не ново.

    Видать, стал я матёрым конвертатором, ничего не удивило)

    Reply ↓
  18. Азбука Морзе

    (15)formix

    Синтаксис-помощник:

    Механизм XDTO позволяет создать модель представления данных (модель типов и значений), которая, с одной стороны, обеспечивает возможность просто и естественно манипулировать данными в среде 1С:Предприятия 8, а с другой стороны, данная модель хорошо приспособлена для прозрачного преобразования данных в другие форматы, главным образом XML.

    На практике достаточно:

    1.создать модель документа «Ляляля» в базе приемнике

    2.создадать и описать файл для записи данных в xlm-формате

    ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();

    НоваяЗаписьXML = Новый ЗаписьXML;

    ФайлXML = ОсновныеПараметры.ФайлВыгрузки;

    НоваяЗаписьXML.ОткрытьФайл(ФайлXML, ПараметрыЗаписиXML);

    ЗаписьСообщения.НачатьЗапись(НоваяЗаписьXML, СтрокаТаблицыИнформации.УзелИнформационнойБазы);

    // из описания типов фабрики XDTO выберем нужные для создания объектов

    Фабрика = ФабрикаXDTO;

    документыТип = Фабрика.Тип(«http://www.lalala.ru», «Документы»);

    // дальше объектные реквизиты и табличные части

    ЛяляляТип = ДокументыТип.Свойства.Получить(«ляляля»).Тип;

    ТЧляляТип =ЛяляляТип .Свойства.Получить(«ТЧляля»).Тип;

    ЭлементТЧляляТип =ТЧляляТип.Свойства.Получить(«ЭлементТЧляля»).Тип;

    3.запросом получить все необходимые данные для заполнения ляляля-объекта

    4. обработать выборку:

    Документы = Фабрика.Создать(документыТип);

    Пока Выборка.Следующий() Цикл

    //создадим объект XDTO и заполним его

    ЛяляляОбъект = Фабрика.Создать(ЛяляляТип);

    ЗаполнитьЗначенияСвойств(ЛяляляОбъект, Выборка)

    документыТип.ляляля.Добавить(ЛяляляОбъект);

    КонецЦикла;

    5. закончить формирование XML-файла

    Фабрика.ЗаписатьXML(НоваяЗаписьXML, Документы);

    ЗаписьСообщения.ЗакончитьЗапись();

    НоваяЗаписьXML.Закрыть();

    Reply ↓
  19. AlexO

    Курсы — это когда дают знания, которые потом народ не знает, куда применить.

    Все это делается более наглядным и быстрым способом — через DBF.

    Reply ↓
  20. AlexO

    (17) sa1m0nn,

    нет, просто тут затронута сугубо узкая специфика.

    И все делается кодом — все преимущества КД сведены только к выгрузке в XML.

    Reply ↓
  21. Tishu

    Из всей неисчерпаемой как атом КД можно зазубрить один приём — в ПВД создается таблица значений по структуре совпадающей с объектом из Приемника и вызывается ПКО — и можно быстро решать массу одноразовых задач. Достаточно посмотреть примеры конвертаций из КД.

    Reply ↓
  22. AlexO

    (21) Tishu,

    «одноразовых» — это только создание в приемнике тех объектов, которых нет с источнике.

    Reply ↓
  23. saiten

    (19)

    Все это делается более наглядным и быстрым способом — через DBF.

    Кому-то каменным топором удобнее, кому-то — станком с ЧПУ… Каждому своё.

    Reply ↓
  24. INSh

    Человек, победивший КД, уже достоин уважения 🙂

    А еще этот человек не поленился и поделился своими достижениями!

    Молодец! Плюс.

    Reply ↓
  25. karakozov

    XDTO Конечно отличный механизм, и не буду защищать КД, но тем не менее очень часто нужно сделать обмен и очень быстро, правильно описать большие объемы по средствам XDTO это то же серьезная работа, особенно если меняешься между разными структурами метаданных или вообще между 77 -> 8.2 . Или еще усложним, из 8.2 в иные реляционные структуры с извесной нам структурой но не свойственной 1С источнику вообще по структуре МД.Имеет место быть в общмею

    Reply ↓
  26. AlexO

    (23) saiten,

    ну конечно, чем непонятнее и замуторнее — тем лучше: и сам не понимаешь, что там делается, и коллеги ничего не разберут, но зато сколько таинственности и значимости… 🙂

    А вот и слушатели под стать:

    Человек, победивший КД, уже достоин уважения
    Reply ↓
  27. DieseL_OFF

    Эххх мне бы лучше другое

    Reply ↓
  28. saiten

    (26) Думаю, эта тема мусолилась уже достаточно, чтобы не поднимать её ещё раз. А непонятность, собственно, — вещь относительная.

    Reply ↓
  29. Sasha255n

    Спасибо очент необходимое и интересное ренение

    Reply ↓
  30. Sasha255n

    Как алтернатива КД имеет место на существование спасибо

    Reply ↓
  31. vkr

    (19) AlexO

    Да, Вы правы…

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

    Можно из одного большого выгруженного файла с кучей информации брать

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

    объектов «на лету». Причем, для совершенно разных, иногда очень слабо

    совместимых конфигураций ( даже и не 1С-овских иногда 🙂 )

    Но, все равно, автору большое спасибо за подробное описание процесса !

    Reply ↓
  32. kurvik

    Очень интересное решение.В практических делах пригодиться,особенно если работаешь с разными структурами метаданных или вообще между 77 -> 8.2 надо делать переброску.

    Reply ↓
  33. fnv

    Спасибо за информацию) Оч. сложные приемы конвертации, я бы через OLE, наверное, делала, если бы мне пришлось делать такой перенос)

    Reply ↓
  34. Franchiser

    Нового ничего не узнал, но статья заслуживает уважения. Рекомендую прочитать методичку О. Кузнецовой, все эти моменты там есть.

    Недостаток использования переменной ВыборкаДанных с моей точки зрения — слишком много написанного кода, не всегда наглядного. То есть чтобы понять как какой объект или свойство трансформируется нужно читать весь код в обрабочике «передобработкой» ПВД. Кроме того фильтры при выгрузке из 7.7 работать не будут.

    В КД есть более эффективные и наглядные механизмы: использование переменных ВходящиеДанные и Исходящиеданные, а также КлючВыгружаемыхДанных, функции ВыгрузитьПоПравилу(). Возможно в этой задаче разница особенно и не заметна, но в основной массе задач, использование указанных мной переменных более оправдано.

    Reply ↓
  35. &rew

    Да, статья полезная. Подобный способ сам использовал при переносе из самописной 7.7 в типовую УТ 10.3, кстати методичка Кузнецовой мне помогла.

    Вообще КД интересная штука, иногда осознание того, как работает правило приходит только после создания этого правила.

    Reply ↓
  36. &rew

    Кстати белый серого сейчас через бедро на иппон бросит.

    Reply ↓
  37. echo77

    (0) ИМХО, для каждого ПКС в ПГКС создавать обработчик:

    Значение = ОбъектКоллекции.ИмяКолонкиТаблицыЗначений
    

    не надо

    Reply ↓
  38. Romany

    (34) Franchiser, Здравствуйте. Как раз разбираюсь с этими переменными, есть много вопросов. Так например задача такая — Для простоты будем считать, что конфигурации самописные, и разные по структуре. В источнике есть документ, в приемнике надо из этого документа создать два объекта 1) справочник. 2) РегистрСведенийЗапись. Пытаюсь сделать так. 1) ПКО — Документ ->Справочник,

    2) ПКО Источника нет -> РегистрСведенийЗапись, ПКС — В приемнике — структура регистра (3 поля), стоит флаг «Получить из входящих данных». Далее в ПВД Документ. В обработчике «ПослеВыгрузки» запросом получаю таблицу движений документа, для переноса их в регистр сведений в приемнике. Тут же надо вызвать функцию «ВыгрузитьПоПравилу()», но вот сложности. В какие параметры, чего пихать, и как это вообще должно работать. То есть, можно ли в параметр ИсходящиеДанные записать таблицу значений (Выгрузку запроса) или создать выборку, и в цикле формировать структуру, и вызывать выгрузить по правилу. Скажу сразу, в моем случае, ни так ни эдак не работает. Обмен происходит по средствам типовой обработки обмена. Если не сложно расскажите в двух словах, как правильно с этим работать, и использовать.

    Reply ↓
  39. ultrannge89

    Добрый день. А есть ли возможность отследить в событии после загрузки, попал ли определенный документ в выгрузку? Мне важно знать есть ли в файле, другой документ по такому же договору как мой, только с другим видом… Не могу нигде найти(

    Reply ↓
  40. Pirat-37

    (39) ultrannge89, через [Сообщить()] выводите, в событии [При загрузке].

    Reply ↓
  41. nems

    Здраствуйте! Подскажите, плиз, как перенести справочник Номенклатура по отбору

    ВходящиеДанные = Новый Структура;
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    | ТоварыОрганизацийОстатки.Номенклатура
    |ИЗ
    | РегистрНакопления.ТоварыОрганизаций.Остатки КАК ТоварыОрганизацийОстатки
    |ГДЕ
    | ТоварыОрганизацийОстатки.КоличествоОстаток > 0»;
    
    Результат = Запрос.Выполнить();
    
    Выборка = Запрос.Выполнить().Выгрузить();
    
    
    ВходящиеДанные.Вставить(«НоменклатураТабл», Выборка);
    
    ВыгрузитьПоПравилу(,,ВходящиеДанные,,»Номенклатура1″)
    

    Показать

    Выгрузка проходит успешно.

    Но есть проблема: Как правильно задать ПКО и ПКС ?

    Reply ↓
  42. Kvitka_ru

    Спасибушки! безценная консультация!!

    Reply ↓
  43. echo77

    Обычно весь выгружаемый объект формируют в ПВД, а не в ПКГС и разных местах.

    Reply ↓
  44. SergeMalikov

    (43) Да. Можно было бы сформировать в ПВД структуру соответствующую объекту в приемнике и передать нужному ПКО. Это был бы более наглядный вариант.

    Reply ↓

Leave a Comment

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