Вывод Таблицы Значений или Дерева Значений на экран управляемой формы без объявления колонок в реквизитах формы




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

10 Comments

  1. json

    Очень хорошо, что ваши процедуры универсальны (это редкость на ИС)

    НО есть несколько моментов, которые [лично мне] могут помешать применить ваши процедуры

    1. Самодокументируемое название методов — из названия методов должно быть однозначно понятно, что данный метод делает (например, СоздатьКолонкиТаблицыНаУправляемойФорме() ). Без необходимости изучения кода самого метода. Иначе возникают сложности с читаемостью и пониманием при а) вызове метода, б) при понимании кода, из которого вызывается данный метод.

    2. Неиспользуемые переменные (например, цЭто и Вариант), а также невыполняемые ветки в операторах Если

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

    4. Большое количество цифр в именах переменных — является моветоном (например, цСхемаКомпоновкиДанныхИсточникТабДок2), вызывает недоверие.

    Высказал только самые критичные на мой взгляд недочеты.

    Несмотря на мою критику, хочу отметить, что заметна большая проделанная работа (и по написанию процедур, и по подготовке статьи)

    Плюс однозначно.

    Reply
  2. fancy

    Спасибо за статью, вчера как раз воспользовался, правда пришлось побиться с добавлением колонок реквизита формы ДеревоЗначений — смог добавить лишь только тогда, когда само дерево добавляю в реквизиты формы программно, если же дерево создать в конфигураторе, то колонки никак не хотели добавляться

    Reply
  3. json

    (2) fancy, да, я тоже сталкивался с этим. Проблема в том, что если колонка добавлена из конфигуратора, то ни колонку реквизита, ни колонку табличного поля на форме удалить программно нельзя. И это все осложняется тем, что в коде нельзя определить, добавлялась колонка программно или через конфигуратор. Единственный костыль, который я тут нашел — использование попытки. Колонки из реквизита на таблицы нужно удалять по одной в попытке (а не сразу всем массивом), и перед добавлением проверять наличие. При обновлении колонок табличного поля — тоже нужно удалять колонки в попытке и перед добавлением — проверять наличие.

    Reply
  4. pavley2002

    (2) fancy, Процедуру СоздатьКолонкиУпр() можно применять только для программно добавленных колонок. Это обусловлено применением метода ВсеЭлементыФормы.Удалить(), в 1С:описании которого непосредственно указано:- «Доступно удаление только ранее программно добавленного элемента».

    Для устранения возникшей не ясности, в описание процедуры СоздатьКолонкиУпр() добавлена строка — «Причем, для этого реквизита состав колонок указанный в управляемой форме должен быть пустым». Спасибо за указание на неточность.

    Reply
  5. pavley2002

    (3) yurii_host,

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

    Однако, сама проблема дублирования имён при программном заполнении колонок следующей коллекции значений существует и требует методологической постановки задачи с последующем решением.

    Алгоритм близкий к по элементной проверке предложен в http://infostart.ru/public/536800/ . Без функции ПроверитьДублиИменКолонок() в указанной статье невозможно решить поставленную там задачу.

    Reply
  6. json

    (5) не понимаю, зачем проверять дубли. Сначала удаляем все колонки, которые можем удалить. Затем добавляем колонки в цикле. Перед добавлением проверяем, присутствует ли колонка с таким именем в коллекции колонок. Если присутствует, то переходим к следующей итерации цикла.

    Прикладываю работающий пример. Данный набор процедур использую уже года два. Проверено в продуктиве много раз

    Попытка используется два раза, что некрасиво. Но других решений пока не нашел.

    Отмечу, что в приведенном примере колонка Склад — добавлена через конфигуратор, а остальные колонки — добавляются программно.

    Подход универсальный и не требует какой-то специальной методологической постановки задачи

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

    Reply
  7. kuzyara
    &НаСервере

    Процедура СоздатьКолонкиУпр(ФормаЭта

    Клинический случай. Дальше читать не стал.

    Reply
  8. pavley2002

    (7) kuzyara,

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

    Reply
  9. almas

    Скачал, посмотрел. Несмотря на значимость обработки ощущение отвратное. Черт нельзя было малость в удобоваримый читаемый порядок все привести???

    Reply
  10. pavley2002

    (9) almas,

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

    Reply

Leave a Comment

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