Месяц назад я уже писал статью о том, как можно реализовать последовательный ввод данных для бота ВК в формате анкеты. И в тот раз рассматривался вариант с использованием базы данных, где, собственно, и хранились промежуточные ответы пользователей. Сегодня же решил сделать нечто похожее, но уже без БД, а с помощью файлов.
Шаг 1: Принцип
Как ни крути, а промежуточные ответы надо как-то запоминать и в нужный момент доставать, поэтому сейчас будем глядеть в сторону файлового хранения. Ничего заумного тут нет, просто всё будем писать в массив и обновлять его каждый раз при помощи функции file_put_contents().
Шаг 2: Storage
Первым делом нужно сделать хранилище, для этого создаю папку storage, а в ней ещё два файла (CtxStorage.php и storage.php):
Про storage.php я уже чутка выше рассказал, файл будет непосредственно выполнять функцию хранения информации. В него потребуется написать всего одну строку кода:
<?php
return array();
CtxStorage - абстрактный класс со статическими методами, которые будут отвечать за логику наших стейтов. Всего в нём будет 5 методов, больше, думаю, никогда и не понадобится.
<?php
namespace storage;
abstract class CtxStorage
{
// Содержимое класса
}
Метод record()
private static function record( $arr )
{
$str = "<?php\n\nreturn " . var_export( $arr, true ) . ";\n";
return file_put_contents( 'storage/storage.php', $str, LOCK_EX );
}
На вход метод получает массив (его мы будет формировать в других методах). Далее создаётся переменная $str, в неё записывается интерпретируемое строковое представление массива $arr с помощью функции var_export().
На текущий момент в переменной $str содержится строка1 типа "<?php return array ( '*userID*_*peerID*' => array ('status' => 1,'data' => array ( /***/ ) ) );". Ничего непонятно, но пока достаточно увидеть то, как сработала функция var_export(). Если её убрать - то в $str запишутся только значения массива.
Ну, и в конце концов, всё то, что находится в переменной $str (ту самую непонятную строку1), нужно вставить в файл storage.php с помощью file_put_contents().
Метод create()
public static function create( $user_id, $peer_id, $data )
{
$arr = require 'storage/storage.php';
$arr[$user_id . '_' . $peer_id] = [
'status' => 1,
'data' => $data
];
return self::record( $arr );
}
Метод будет использоваться каждый раз при старте заполнения анкеты. На вход передаётся user_id, peer_id и пустой массив2 с теми полями, которые предполагается заполнить по мере прохождения анкеты. То есть, если мне нужно получить от юзера, к примеру, имя, фамилию и возраст, то сей массив будет выглядеть так (ключи можно придумать любые, главное - в них не запутаться):
[ 'first_name' => '', 'last_name' => '', 'age' => '' ]
Далее в основной массив из файла storage.php мы просто добавляем еще один субмассив. В качестве ключа используем peer_id и user_id. И не стоит забывать, что в общем массиве могут находиться одновременно несколько анкет от разных пользователей.
Осталось только обновить массив в файле storage.php, используя уже рассмотренный и написанный метод record().
После всех этих манипуляций получаем следующее:
<?php
return array (
'123_321' => array (
'status' => 1, // Статус анкеты, будет увеличиваться на едицницу, пока не будут заполнены все поля анкеты
'data' => array (
'first_name' => '',
'last_name' => '',
),
),
// Тут могут быть еще какие-то анкеты
);
Метод set()
public static function set( $user_id, $peer_id, $text, $state )
{
$arr = require 'storage/storage.php';
$arr[$user_id . '_' . $peer_id]['status']++; // Статус увеличиваем на единицу
$arr[$user_id . '_' . $peer_id]['data'][$state] = $text; // Записываем ответ пользователя в стейт с соответствующим названием
return self::record( $arr );
}
Нужен, чтобы записывать полученные от юзера данные. На вход передаётся user_id, peer_id, текст сообщения юзера и название стейта, который нужно обновить. Названия соответствуют ключам массива2, который мы передаём в метод create().
Метод get()
public static function get( $user_id, $peer_id )
{
$arr = require 'storage/storage.php';
return $arr[$user_id . '_' . $peer_id] ?? null;
}
Возвращает массив с анкетой пользователя. Ключ массива, напомню, имеет вид userID_peerID.
Метод delete()
public static function delete( $user_id, $peer_id )
{
$arr = require 'storage/storage.php';
unset( $arr[$user_id . '_' . $peer_id] );
return self::record( $arr );
}
После того, как юзер полностью заполнил анкету - её можно удалить, а данные перенести на постоянное место хранения (если в этом, конечно, есть нужда). Удалить анкету в общем массиве можно прибегнув к использованию функции unset().
Всё. С хранилищем мы закончили. Отныне его можно подключать в любые свои проекты и использовать как библиотеку.
Шаг 3: Применение хранилища
В индексном файле создаю структуру для дальнейшей работы с сообщениями. Подробно уже не объясняю, поскольку в предыдущей статье писал об этом.
<?php
require 'simplevk-master/autoload.php'; // Подключение SimpleVK
require 'storage/CtxStorage.php'; // Подключение класса CtxStorage
$vk = \DigitalStar\vk_api\vk_api::create( 'ключ', 'версия api' )->setConfirm( 'возвращаемая сервером строка' );
$vk->initVars( $peer_id, $message, $payload, $vk_id, $type, $data ); // Инициализация переменных
if ( $type == 'message_new' )
{
// Тут продолжим кодить
}
В переменную $ctx запишем методом CtxStorage::get() анкету юзера (если, конечно, она есть). Если нет, то запишется null:
$ctx = \storage\CtxStorage::get( $vk_id, $peer_id );
Теперь приступаем к обработке команд и ответов пользователя. Начинаем с команды для старта (у меня это будет /заполнить), которая создаст новую анкету (метод CtxStorage::create()), а далее бот попросит пользователя ввести имя:
if ( $message == '/заполнить' )
{
\storage\CtxStorage::create( $vk_id, $peer_id, [ 'name' => '', 'age' => -1, 'city' => '' ] );
$vk->sendMessage( $peer_id, 'Укажите имя' );
}
Через elseif проверим, существует ли анкета у этого пользователя. Если да, то значит будем определять по статусу, что дальше спрашивать у него:
else if ( isset( $ctx ) and $ctx )
{
switch ( $ctx['status'] )
{
// Тут будет проверка по статусам
}
}
В моём случае проверки по статусам будет 3, так как будет 3 поля в анкете (имя, возраст и город проживания). В первых двух шагах просто получаем и записываем данные собесдника:
case 1:
{
\storage\CtxStorage::set( $vk_id, $peer_id, $message, 'name' );
$vk->sendMessage( $peer_id, 'Укажите возраст' );
break;
}
case 2:
{
\storage\CtxStorage::set( $vk_id, $peer_id, $message, 'age' );
$vk->sendMessage( $peer_id, 'Укажите город проживания' );
break;
}
На третьем шаге можно сохранить, например, в БД полученные данные (если есть необходимость). Я же просто отправлю оформленную анкету для просмотра пользователю и удалю её из временного хранилища с помощью CtxStorage::delete()
case 3:
{
\storage\CtxStorage::set( $vk_id, $peer_id, $message, 'city' );
$name = $ctx['data']['name'];
$age = $ctx['data']['age'];
$city = $message;
$vk->sendMessage( $peer_id, "Имя: $name\nВозраст: $age\nГород: $city" );
\storage\CtxStorage::delete( $vk_id, $peer_id );
break;
}
Шаг 4: Проверяем
Всё работает в точности так же, как и при использовании базы данных в кач-ве временного хранилища :)
Архив с исходниками:
Перед публикацией, советую ознакомится с правилами!
Sitemap генератор
7-11-2023, 16:38Что такое MD5 и как она
10-11-2023, 22:05Приветственное письмо по
7-11-2023, 15:58Как включить gzip-сжатие на
14-11-2023, 22:08Генератор случайных паролей
5-11-2023, 15:45Массивы в jаvascript: виды,
18-11-2023, 22:57Способы увеличения скорости
21-11-2023, 23:16Методы массивов в
24-11-2023, 23:33Использование фреймворков в
30-11-2023, 23:39Работа с асинхронным кодом
26-11-2023, 23:36 Нашли ошибку?
Вы можете сообщить об этом администрации.
Выделив текст нажмите CTRL+Enter