Глобальные переменные в контексте сервера 8.2. Простое решение.




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

29 Comments

  1. bazilisa

    и зачем это, два раза прочитал не понял

    Reply
  2. strange2007

    Очень ценная информация. Жаль раньше сам не додумался :))

    Reply
  3. xMas

    Что-то есть подозрение, что переменная будет жить 20 минут (а может даже и всего 5)

    Reply
  4. Expert1C

    (3) да, конечно. Если сеанс будет жить 20 минут (или всего 5)

    Reply
  5. tarroman

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

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

    Reply
  6. tarroman

    Я бы еще заголовок темы поменял. Ну как-то не совсем он коррелирует с описанием. Например, из первого предложения темы — «Реализация глобальных переменных и обращение к ним на сервере 8.2». 😀

    Reply
  7. Expert1C

    (5) данный пример максимально наглядно показывает, что возможно сохранение ссылки на объект. Что за объект — это уже не важно.

    Количество сохраняемых объектов платформа не ограничивает.

    Чиститься будет, если не будет циклических ссылок

    Reply
  8. Expert1C

    (6) как говорила наша химичка, что пнем по сове, что совой об пень…

    Reply
  9. tarroman

    (7) Я бы сказал, что данный пример показывает возможность сохранения соответствия в рамках сеанса и обращения к нему в первую очередь. А что запихано в соответствие — да что угодно, благо там нет ограничения на типы хранимых в соотв. объектов. 😉

    Reply
  10. Expert1C

    (9) почему соответствие? это может быть структура, ТЗ, ВК, …

    смысл в том, что хранится именно ссылка, а не копия объекта

    Reply
  11. tarroman

    (10) в примере то именно соответствие 🙂 Для меня соответствие — это не ссылка. Это агрегатный объект/тип:) А хранить наверное можно все, что может возвращать подобная функция с указанными свойствами, либо агрегатный объект/тип, ею возващаемый.

    Reply
  12. Expert1C

    (11) соответствие для демонстрации выбрано только потому, что в нем проще хранить уникальные значения (дату).

    А агрегантный объект может быть либо ссылкой (как в данном примере) либо копией (в типовых 8.1 можно посмотреть функцию глПолучитьЗначениеПеременной(…) — название может быть несколько не такое)

    Reply
  13. tarroman

    (12) Вот и замечательно. В статье отражены и другие аспекты демо-примера 🙂

    Reply
  14. milanse

    Плюсанул, ком объекты, кстати тоже кешируются.

    Reply
  15. Expert1C

    (14) см. (10)

    Reply
  16. kravchuk

    Может пригодится.

    Reply
  17. artbear

    Плюсанул.

    ИМХО в 8.2 в данном вопросе как-то все очень извращенно получилось 🙁

    Reply
  18. smilohov

    Спасибо, помогло! Плюсанул.

    Reply
  19. rasswet

    расскажите на примере, плиз, зачем это нужно?

    Reply
  20. Expert1C

    (19) не надо придумывать задачу по возможностям, надо искать возможности для решения задач

    Reply
  21. korsar-81

    СУПЕР — это то что я долго искал, большое спасибо

    Reply
  22. ZLENKO

    Если быть еще более точным, то читать надо не реже чем каждые 6 минут и даже в этом случае через 20 минут после вычислени все равно «умрет». А может и раньше если не повезет и серверу станет мало памяти.

    Возможность очень интересная, но очень неуниверсальная 🙁 т.к. нет возможности явно управлять временем жизни кеша.

    Reply
  23. ValeriVP

    (22) да, да, да.

    на момент публикации еще небыло столь подробных комментариев от 1С, а сечас уже есть. и в связи с этим данный механизм уже не столь красив как казалось.

    Reply
  24. jsmith

    Очень интересно. Спасибо

    Reply
  25. d0dger

    Наткнулся на публикацию, а чем параметры сеанса в качестве глобальных переменных хуже?

    Reply
  26. saver77

    Спасибо! Отлично работает.

    Внимание! В 8.3 не работает способ с использованием ПараметрСеанса, описанный тут: http://infostart.ru/public/62410/, выдаёт ошибку «Переданное значение не может быть помещено во временное хранилище».

    Reply
  27. JesteR

    Из документации:

    Сохраненные значения удаляются:

    Если свойство установлено в значение На время вызова:

    ● на стороне сервера – при возврате управления с сервера;

    ● на стороне клиента – при завершении работы процедуры или функции встроенного языка верхнего уровня (вызванной системой из интерфейса, а не из другой процедуры или функции встроенного языка);

    Если свойство общего модуля установлено в значение На время сеанса:

    ● на стороне сервера – при окончании сеанса;

    ● на стороне клиента – при закрытии клиентского приложения.

    Сохраненные значения будут удалены:

    ● на сервере, в толстом клиенте, во внешнем соединении, в тонком клиенте и в веб-клиенте с обычной скоростью соединения – через 20 минут после вычисления сохраняемого значения или через 6 минут после последнего использования;

    ● в тонком клиенте и веб-клиенте с низкой скоростью соединения – через 20 минут после вычисления сохраняемого значения;

    ● при нехватке оперативной памяти в рабочем процессе сервера;

    ● при перезапуске рабочего процесса;

    ● при переключении клиента на другой рабочий процесс.

    После удаления значений вызов экспортируемой функции выполняется как при первом вызове.

    Reply
  28. ybatiaev

    А нельзя ли ТАК правильно написать программный код, где «КЕШируемый» вызов будет получать данные только один раз( а не крутить вызовы в теле модуля)? И управление КЕШом всё-таки связать с видимостью ПЕРЕМЕННЫХ? Если пользователь «ушёл с модуля» — почистился КЕШ переменных значений модуля.

    Вообще, как бы желательно, САМОМУ (программно) чистить КЕШ НЕ НУЖНЫХ значений(по типу деструктора).

    И ещё. Если в общем модуле с повторным использованием выбран «на время сеанса», то чем ЭТО в принципе отличается от использовании параметров сеанса? Это я про «мусор» как в конфигурации, так и в головах

    Reply
  29. for_sale

    Для решения каких-то задач этот механизм наверняка нужен, удобен и хорош, но никакого отношения к «глобальным переменным на сервере» он не имеет, зачем писать такие вводящие в заблуждения названия статьям? Это «сохранение значения на сервере на время сеанса», а не глобальная переменная.

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

    Reply

Leave a Comment

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