Хранение текстов запросов в справочнике и выполнение в общем модуле




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

25 Comments

  1. mr.Samuelson

    Боже, дык в конфе тысячи запросов. Не выносить же их все в справочники… Подобные частые переделки запросов только для отчетов наверное нужны, но при использовании СКД или там внешних отчетов — перезаход пользователей также не нужен.

    Reply
  2. Franco



    Дано: разрабатываемая конфигурация.

    Reply
  3. Yashazz
    Идея взята из книги Гетц, Литвин, Бэрон ‘Access. Сборник рецептов для профессионалов’.

    Оказывается, у этих товарищей и у меня идеи совпадают. Приятно узнать )))

    Хотя мне больше нравится хранить фрагменты кода, в т.ч. и с запросами: http://infostart.ru/public/168168/

    Reply
  4. Franco

    …мне больше нравится хранить фрагменты кода, в т.ч. и с запросами: http://infostart.ru/public/168168/

    Grazie, Yashazz, за подсказку.

    Кому-то, конечно, может и не понравится хранение кода в справочнике (?либо регистре сведений) — в каком-то отношении будут правы, например, сославшись на регламенты. Однако по мне идея прекрасна — можно использовать такую систему при разработке и отладке конфигураций. А выпускаемую в работу конфигурацию уже заполнять модули кодом.

    И ещё — эту библиотеку можно использовать как сборник рецептов.

    Reply
  5. zqzq

    (2) Т.е. потом все эти запросы мигрируют в код? Не проще сразу там писать? А для отладки есть инструменты, например как в ИР вызывать из режима отладки функцию От(Запрос), которая в модальном режиме открывает консоль запросов с установленными параметрами, текстом.

    Reply
  6. Yashazz

    Обсуждаемые возможности хороши, когда скелет конфигурации менять нельзя, а задача либо неясна, либо часто меняется. Плюсы — гибкость, минусы — трудности поддержки, отладки, прозрачности, целостности. Инструмент не для всех случаев, но иногда только он и выручает, когда надо вроде бы и штатно, и «по месту напильником». Лишь бы в конфе были такие места, предусмотренные для вмешательства напильником. Эдакие «порты», как бы.

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

    Reply
  7. AlX0id

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

    Динамическое обновление никто не отменял, собственно.

    Reply
  8. Franco

    (7) AlX0id,

    1.Динамическое обновление стараюсь использовать как можно меньше. Всё равно после 3-4-го обновления RPHost падает, создаётся дамп.

    2.Работа на БОЛЬШОЙ базе и маленькой нисколько не различима — выгрузка здесь не при чём — запросы либо в конфигурации (и с данными не связаны), либо в справочнике. Выполняются в общем модуле.

    Reply
  9. Franco

    (6) Yashazz,

    Вновь же, на стадии отладки.

    Reply
  10. AlX0id

    (8) ocnarf_ff,

    1. Ну это как бы проблемы Вашего сервера.

    2. Значит, Вы не работали с БОЛЬШИМИ базами.

    Как это выглядит на данный момент моими глазами: Вы пытаетесь перенести проблемы администрирования на программистов. Может быть, стоит завести нормального админа? )

    Reply
  11. Franco

    (10) rus128,

    спс, мне не сильно важно плюс.

    Если желаете, для Вас переведу?

    Reply
  12. Franco

    (11) AlX0id,

    1.Не стоит ругать админа. В 8.2 при динамическом обновлении нет проблем.

    Отладку запросов так делать легче чем при динамике — нет падений RPHost и нет сообщений пользователям.

    2.Чем может быть отличаться конфигурация большой базы от конфигурации маленькой? При чём выгрузка в отладке запросов?

    Reply
  13. rus128

    (12) За меня не беспокойтесь — мои знания английского + 1С позволяют понять, какие методы вызываются.

    а вот новичкам — возможно, было бы полезнее на русском прочитать…

    Reply
  14. AlX0id

    (13) ocnarf_ff,

    2. Наверное, Вы правы в этом — объем данных будет влиять только в случае реструктуризации, а тут ваш механизм ничем не поможет.

    Reply
  15. Franco

    (14) rus128,

    Английский наше всё — так, кажется, выражение говорится?

    Но всё-таки приму к сведению, благодарю. К тому методика разработки указывает на русский язык.

    Reply
  16. Ava_1c

    Успешно использовали похожий прием еще на 8.1.

    Была самописная конфигурация, стояла задача классифицировать некоторые объекты. Под «классификацией» понималось присвоение объекту некоторой категории (категория — элемент справочника). Что-то вроде ABC-анализа номенклатуры/контрагентов, только сложнее.

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

    Этакое бинарное дерево из узлов-запросов с листьями-категориями.

    Визуально все это рисовали в виде блок-схемы (самая большая классификация — на печати формат а1, больше 50 «условий» в схеме), получилось довольно наглядно. Каждый день обсчитывали по 4-5 классификаций, в каждой порядка 100к объектов.

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

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

    Руководство было в восторге. =)

    Reply
  17. AganinEvgeniy

    (7) AlX0id, Ерунда. Главное тут сам принцип. А не конкретное его воплощение. Я допустим, привык пользоваться внешним построителем запросов или же просто в конфигураторе пишу внешние отчеты или обработки табличных частей. Но это не повод хаять на человека, за неплохую задумку. Меня тоже кстати всегда напрягает обновление базы, которое нужно провести ИМЕННО СЕЙЧАС, для выполнения задания директора. А в базе работает полно пользователей. И не говорите про динаму … с этим сплошным глюком 1 раз столкнулся … после восстановления бд из архива … больше динамическим обновлением не пользуюсь. ПРИНЦИПИАЛЬНО! Даже когда нужно просто в отчете макет подправить. А этот вариант … он ничем не хуже других и имеет право на жизнь.

    Reply
  18. Franco

    (18) AganinEvgeniy,

    Grazie.

    Конечно же, это задумка для разрабатываемой, а не тиражируемой конфигурации.

    PS.И динамика — это величайшее зло. Особенно в 8.3

    Reply
  19. AlX0id

    (18) AganinEvgeniy,

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

    Я и не хаю особо — просто пытаюсь найти применение этому механизму. Пока не нашел )

    Reply
  20. AganinEvgeniy

    (20) AlX0id, я в первый раз про динамическое обновление узнал на очном курсе 1с, проходившем в УЦ1, и опробовал его в деле ТОЛЬКО после этого (и кстати пользовался довольно аккуратно и только в случае обновления, которое не затрагивает данные в ИБ, такие обновления я всегда проводил в обычном режиме … береженого свои боги берегут и чужие не трогают) и в одном из обновлений вылез косяк, что при обновлении только одного макета!!! в отчете у меня база полетела наглухо, в последствии вычитывал описание, а после уже курил форумы и описания ошибок, выявленых при том или ином обновлении. И не раз натыкался на то, что в том или ином релизе не корректно происходит обработка динамического обновления то из-за взаимных блокировок, то ещё по какой причине. По поводу того, что данный механизм мало применим на практике, согласен, но сам принцип довольно интересен. И думаю с него можно поиметь несколько реализаций довольно приятных. А если удастся это реализовать на полностью типовом решении … цена такому решению будет очень высока. Во всяком случае я бы с радостью попытался использовать это.

    Reply
  21. Yashazz

    (7) Какие бы сказки вам ни рассказывали про «это волшебное динамическое обновление» — наткнётесь на первый непредсказуемый косяк, угробите базу — тогда всё поймёте. Только ваших пользователей жаль.

    (17) Решение, ссылку на которое я подкинул, появилось чуть ли не в 8.0 году так в 2006, а концепция была ещё в 7.7 и действовала через внешку-ert, модуль которой брался из формируемого файла. Ваше решение считаю красивым, сам до уровня блок-схем не доходил. Концепция правильная и на практике нужная.

    Reply
  22. AlX0id

    (21) AganinEvgeniy,

    Ну, ребят, сколько уже с той поры утекло времени-то )

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

    Reply
  23. AlX0id

    З.Ы. Повторюсь — против решения как такового не имею ничего против. Сами так делали, когда надо было настроить расчет зарплаты на одном предприятии.

    Мало того — делали и построитель отчетов на базе справочника с СКД.

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

    З.З.Ы. Чего бы уж сразу не сделать справочник с кусками кода тогда? )

    Reply
  24. AganinEvgeniy

    (23) AlX0id, Согласен по поводу того, что проблема не частая … но мне и 1 раза выше крыши хватило. Проще подождать окончания рабочего дня и уже нормально запустить обновление в монопольном режиме, чем потом страдать с восстановлением из бэкапа.

    Reply
  25. Franco

    Если, конечно, есть окончание рабочего дня — а если работа ведётся все сутки?

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

    Reply

Leave a Comment

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