Интерфейс взаимодействия с Telegram-ботом становится значительно удобнее, если использовать встроенные кнопки. В Telegram API доступны два типа клавиатур: ReplyKeyboardMarkup и InlineKeyboardMarkup. Обе поддерживаются при разработке на PHP с использованием библиотеки Telegram Bot API или фреймворков, таких как php-telegram-bot.
Reply-клавиатура отображается вместо стандартной клавиатуры телефона. Она подходит для часто повторяющихся действий, таких как «Меню», «Помощь» или «Связаться с оператором». Для создания таких кнопок необходимо передать массив массивов кнопок в параметре keyboard, предварительно обернув его в reply_markup с флагом resize_keyboard.
Inline-кнопки встраиваются непосредственно в сообщение и поддерживают обработку нажатий без отправки нового сообщения от пользователя. Они создаются с помощью массива inline_keyboard, где каждая кнопка задаётся параметрами text и callback_data или url. Такой формат отлично подходит для навигации по меню или интеграции с внешними сервисами.
При работе с inline-кнопками важно реализовать обработчик callback_query, который будет получать данные по нажатию и отправлять ответ с помощью метода answerCallbackQuery. Без этого Telegram может воспринимать нажатия как «без ответа», что приводит к снижению отзывчивости интерфейса.
Для повышения надёжности логика формирования клавиатур должна быть выделена в отдельную функцию. Это упрощает масштабирование и поддержку кода, особенно если меню генерируется динамически, например, на основе данных из базы данных или пользовательского состояния.
Подключение библиотеки Telegram Bot API к PHP-проекту
Для работы с Telegram Bot API в PHP необходимо использовать надёжную и актуальную библиотеку. Рекомендуется установить irazasyed/telegram-bot-sdk
через Composer. В корне проекта выполните команду:
composer require irazasyed/telegram-bot-sdk
После установки библиотека автоматически подключится через автозагрузку Composer. Убедитесь, что в вашем скрипте присутствует:
require 'vendor/autoload.php';
Инициализация бота осуществляется следующим образом:
$telegram = new \Telegram\Bot\Api('ВАШ_ТОКЕН_БОТА');
Замените ВАШ_ТОКЕН_БОТА
на актуальный токен, полученный через @BotFather. Проверьте работоспособность, вызвав базовый метод:
$response = $telegram->getMe();
print_r($response);
должен вернуть данные о вашем боте. Если этого не происходит – проверьте токен и наличие расширения curl
в PHP. Без него запросы к API невозможны.
Для отправки запросов из вебхука или CLI убедитесь, что версия PHP не ниже 7.4, и включены расширения mbstring
и json
. Поддержка их обязательна для корректной работы SDK.
При развертывании проекта на сервере настройте права доступа к директории vendor
и проверьте, чтобы она не блокировалась настройками .htaccess или веб-сервера.
Создание обычных кнопок ReplyKeyboardMarkup
В PHP для работы с Telegram Bot API чаще всего используется метод sendMessage
с параметром reply_markup
, содержащим JSON-структуру клавиатуры. Пример:
$data = [
'chat_id' => $chat_id,
'text' => 'Выберите действие:',
'reply_markup' => json_encode([
'keyboard' => [
['📄 Получить отчёт', '📊 Статистика'],
['⚙️ Настройки']
],
'resize_keyboard' => true,
'one_time_keyboard' => false
])
];
file_get_contents("https://api.telegram.org/bot{$token}/sendMessage?" . http_build_query($data));
Параметр resize_keyboard
автоматически подгоняет высоту клавиатуры под количество кнопок. one_time_keyboard
скрывает клавиатуру после выбора одного из вариантов, если установлено в true
.
Текст на кнопках должен соответствовать ожидаемым обработчиком входящих сообщений. Ответы пользователя приходят как обычные текстовые сообщения, поэтому важно правильно распознавать их в логике бота.
Для удаления клавиатуры используйте объект ReplyKeyboardRemove
с параметром remove_keyboard
установленным в true
.
Настройка инлайн-кнопок InlineKeyboardMarkup
Инлайн-кнопки создаются с помощью массива, передаваемого в параметр reply_markup
при вызове метода sendMessage
или editMessageText
Telegram Bot API. Используется структура InlineKeyboardMarkup
, которая включает массив кнопок, сгруппированных по строкам.
Пример формирования двухстрочной клавиатуры с тремя кнопками:
$keyboard = [
'inline_keyboard' => [
[
['text' => 'Кнопка 1', 'callback_data' => 'action_1'],
['text' => 'Кнопка 2', 'callback_data' => 'action_2']
],
[
['text' => 'Сайт', 'url' => 'https://example.com']
]
]
];
$options = [
'chat_id' => $chat_id,
'text' => 'Выберите действие:',
'reply_markup' => json_encode($keyboard)
];
file_get_contents("https://api.telegram.org/bot{$token}/sendMessage?" . http_build_query($options));
callback_data
используется для обработки нажатий внутри бота. Максимум 64 байта.url
открывает внешнюю ссылку в браузере.- Одна строка – один массив кнопок. Порядок важен: он определяет расположение кнопок слева направо.
При обработке нажатий необходимо использовать метод answerCallbackQuery
и проверять значение callback_data
:
$data = json_decode(file_get_contents("php://input"), true);
if (isset($data['callback_query'])) {
$callback_id = $data['callback_query']['id'];
$action = $data['callback_query']['data'];
file_get_contents("https://api.telegram.org/bot{$token}/answerCallbackQuery?" . http_build_query([
'callback_query_id' => $callback_id,
'text' => 'Обработано: ' . $action
]));
}
Для обновления текста и клавиатуры используется метод editMessageText
, обязательны параметры chat_id
, message_id
и новая разметка reply_markup
.
Рекомендации:
- Избегайте дублирующих
callback_data
, если они ведут к разным действиям. - Сохраняйте соответствие между кнопками и логикой обработки нажатий.
- Используйте json_encode с опцией
JSON_UNESCAPED_UNICODE
для корректной передачи текста на русском языке.
Обработка нажатий на инлайн-кнопки через callback_query
При работе с инлайн-кнопками Telegram отправляет боту объект callback_query, содержащий данные, указанные в параметре callback_data кнопки. Для обработки необходимо проанализировать входящий JSON и отреагировать соответствующим образом.
Пример извлечения данных из callback_query:
$update = json_decode(file_get_contents('php://input'), true);
if (isset($update['callback_query'])) {
$callbackId = $update['callback_query']['id'];
$userId = $update['callback_query']['from']['id'];
$data = $update['callback_query']['data'];
// Пример обработки нажатия
if ($data === 'action_1') {
// Отправка уведомления без изменения чата
file_get_contents("https://api.telegram.org/bot/answerCallbackQuery?callback_query_id={$callbackId}&text=Вы выбрали действие 1");
// При необходимости – сообщение пользователю
file_get_contents("https://api.telegram.org/bot/sendMessage?chat_id={$userId}&text=Выполняется действие 1");
}
}
Значение callback_data должно быть коротким (до 64 байт) и однозначно указывать на тип действия. Используйте префиксы или JSON-строки для передачи контекста, например: task_done_42 или {«cmd»:»done»,»id»:42}.
Ответ на callback_query необходимо отправлять в течение 10 секунд. Иначе кнопка будет «висеть» в состоянии загрузки. Используйте метод answerCallbackQuery даже при отсутствии визуального ответа – достаточно передать пустую строку в text.
Если после нажатия требуется изменить текущее сообщение, используйте editMessageText, передавая message_id и chat_id из callback_query:
$messageId = $update['callback_query']['message']['message_id'];
$chatId = $update['callback_query']['message']['chat']['id'];
file_get_contents("https://api.telegram.org/bot/editMessageText?chat_id={$chatId}&message_id={$messageId}&text=Сообщение обновлено");
Рекомендуется валидировать callback_data перед обработкой, чтобы исключить попытки подделки или некорректных данных от клиента.
Передача данных через инлайн-кнопки с параметрами
Для передачи параметров через инлайн-кнопки используется атрибут callback_data. Его длина не должна превышать 64 байта. Формируйте данные в формате, который удобно парсить: например, через разделители или в виде JSON (если укладывается в лимит).
Пример кнопки с параметрами:
$keyboard = [
'inline_keyboard' => [[
['text' => 'Выбрать товар 42', 'callback_data' => 'select:42']
]]
];
При обработке callback-запроса используйте explode() или регулярные выражения для извлечения параметров:
$data = explode(':', $callback_data);
$action = $data[0]; // select
$id = $data[1]; // 42
Если нужно передать несколько параметров, используйте сериализацию в JSON, но убедитесь, что итоговая строка не превышает лимит:
$payload = json_encode(['a' => 'vote', 'id' => 7]);
['text' => 'Голосовать', 'callback_data' => $payload]
При получении:
$data = json_decode($callback_data, true);
$action = $data['a'];
$id = $data['id'];
Избегайте передачи чувствительных данных, так как callback_data видна клиенту через сторонние инструменты. Идентификаторы можно шифровать или хэшировать, если это необходимо.
Оптимизируйте данные под минимальный размер. Используйте короткие ключи, цифровые ID, минимальные форматы. При превышении лимита данные не будут доставлены, и Telegram вернёт ошибку.
Удаление и обновление кнопок в уже отправленных сообщениях
Для управления кнопками в уже отправленных сообщениях в Telegram-боте на PHP используется метод editMessageReplyMarkup
API Telegram. Этот метод позволяет удалить или обновить inline-кнопки, не отправляя новое сообщение. Важно понимать, что изменение кнопок возможно только для сообщений, которые были отправлены ботом и в которых присутствуют inline-кнопки.
Чтобы удалить все кнопки, необходимо отправить пустой объект в параметре reply_markup
. Это приведет к удалению всех inline-кнопок в сообщении, при этом само сообщение останется доступным для пользователя.
Пример удаления кнопок:
$token = "YOUR_BOT_API_TOKEN"; $chat_id = "CHAT_ID"; $message_id = "MESSAGE_ID"; $data = [ 'chat_id' => $chat_id, 'message_id' => $message_id, 'reply_markup' => json_encode(['inline_keyboard' => []]) ]; file_get_contents("https://api.telegram.org/bot$token/editMessageReplyMarkup?" . http_build_query($data));
Для обновления кнопок в сообщении достаточно передать новый набор кнопок в параметре inline_keyboard
. Например, можно заменить старую кнопку на новую или добавить дополнительные кнопки, не изменяя остальной контент сообщения.
Пример обновления кнопок:
$data = [ 'chat_id' => $chat_id, 'message_id' => $message_id, 'reply_markup' => json_encode([ 'inline_keyboard' => [ [['text' => 'Новая кнопка', 'callback_data' => 'new_data']] ] ]) ]; file_get_contents("https://api.telegram.org/bot$token/editMessageReplyMarkup?" . http_build_query($data));
При удалении или обновлении кнопок важно учитывать, что Telegram не всегда немедленно отражает изменения, особенно в случае с большими нагрузками на серверы. В этом случае можно ожидать некоторое время, прежде чем изменения будут отображены на стороне клиента.
Организация многоуровневого меню с кнопками
Для начала необходимо создать кнопку с вызовом следующего уровня меню. Для этого используется массив с параметром «callback_data», который определяет действие, связанное с кнопкой. Рассмотрим пример реализации первого уровня меню:
$keyboard = [ ['Товар 1', 'Товар 2'], ['Меню', 'Назад'] ]; $reply_markup = json_encode([ 'keyboard' => $keyboard, 'one_time_keyboard' => true, 'resize_keyboard' => true ]);
Когда пользователь нажимает на одну из кнопок, бот отправляет данные через callback, например, при нажатии на кнопку «Меню», бот активирует второй уровень меню. Для этого необходимо обработать запрос и вывести новые кнопки. Рассмотрим код для второго уровня меню:
if ($text == "Меню") { $keyboard = [ ['Подменю 1', 'Подменю 2'], ['Назад'] ]; $reply_markup = json_encode([ 'keyboard' => $keyboard, 'one_time_keyboard' => true, 'resize_keyboard' => true ]); // отправляем ответ пользователю sendMessage($chat_id, "Выберите подменю:", $reply_markup); }
Для обеспечения плавности работы меню можно использовать структуру вложенных уровней. Каждый уровень может быть вызван при помощи кнопок, а данные о выбранном пункте передаются через callback, что позволяет легко переключаться между меню и сохранять контекст выбора.
Для повышения удобства пользователя рекомендуется использовать возможность скрытия клавиатуры после взаимодействия, добавив параметр ‘remove_keyboard’. Этот параметр делает взаимодействие с ботом более удобным и не отвлекающим:
$keyboard = [ [['text' => 'Назад', 'request_contact' => false, 'request_location' => false]] ]; $reply_markup = json_encode([ 'remove_keyboard' => true ]);
Кроме того, при реализации многоуровневых меню важно учитывать логику навигации и отмены действий. Для этого можно добавлять кнопки с действиями «Назад» и «Главное меню», что позволит пользователю легко вернуться на предыдущий уровень или сразу на начальную страницу. Важно также правильно обрабатывать ошибочные данные, чтобы не допустить сбоя в работе меню.
Каждый уровень меню должен быть организован так, чтобы пользователю было легко понять, как двигаться по меню, избегая излишней сложности. Простота и логика взаимодействия – залог успешного использования многоуровневого меню в Телеграм-ботах.
Для того чтобы ограничить доступ к определённым кнопкам в Telegram-боте, необходимо учитывать идентификаторы пользователей или их роли. С помощью этого подхода можно показывать кнопки только тем, кто имеет соответствующие права. В этой статье рассмотрим несколько методов реализации такой функциональности на PHP.
Прежде всего, для работы с ролями пользователей вам нужно заранее определить, кто будет иметь доступ к кнопкам. Например, это могут быть администраторы, модераторы или обычные пользователи. Для этого можно использовать идентификаторы пользователей или специальные роли, которые вы будете хранить в базе данных.
- Получите ID пользователя с помощью массива данных, который приходит с запросом от Telegram API:
$user_id = $update['message']['from']['id'];
$allowed_users = [123456789, 987654321];
if (in_array($user_id, $allowed_users)) { ... }
$keyboard = [ ['Кнопка 1', 'Кнопка 2'], ['Кнопка 3'] ];
$telegram->sendMessage(['chat_id' => $user_id, 'text' => 'Выберите опцию:', 'reply_markup' => $keyboard]);
Если вы используете роли, например, «администратор» или «модератор», их можно добавить в базу данных и проверить перед отправкой кнопок. В таком случае код может выглядеть так:
- Запросите роль пользователя из базы данных:
$role = getUserRole($user_id);
if ($role == 'admin') { ... }
Для более сложных систем ролей можно использовать JSON-формат для хранения данных о пользователях и их доступах, что позволяет легко масштабировать и добавлять новые роли.
Также стоит учитывать, что с помощью inline-кнопок можно реализовать динамическое управление доступом. Например, при нажатии на кнопку проверяется роль пользователя, и в зависимости от неё открываются различные действия. Это требует дополнительной логики в обработчиках на стороне бота, но даёт гибкость в управлении функциональностью.