Клавіатури
Reply Keyboard
Reply Keyboard (обычная, или «шаблонная» клавиатура) — это элемент интерфейса Telegram, который заменяет стандартную системную клавиатуру устройства пользователя набором заранее подготовленных кнопок. В отличие от Inline Keyboard, эти кнопки не прикрепляются к конкретным сообщениям, а располагаются в нижней части экрана, прямо под полем ввода текста.
Принцип работы и отличие от Inline Keyboard
Главное архитектурное отличие Reply Keyboard заключается в способе передачи данных на ваш сервер:
- При нажатии на кнопку Reply Keyboard клиент Telegram автоматически отправляет в чат обычное текстовое сообщение от имени пользователя. Текст этого сообщения в точности совпадает с надписью на кнопке.
- Ваш бот получает стандартный объект
Updateс типомmessage. Никаких событий callback_query в данном случае не генерируется. - Пользователь может в любой момент скрыть клавиатуру и написать тот же текст руками — для вашего обработчика на сервере результат будет абсолютно одинаковым.
Reply Keyboard идеально подходит для построения главного меню бота («Каталог», «Профиль», «Корзина»), быстрого выбора ответов в опросах или безопасного запроса конфиденциальных данных (номер телефона, геолокация).
Параметры ReplyKeyboardMarkup
Клавиатура передаётся в параметре reply_markup метода sendMessage (или любого другого метода отправки медиа) в виде JSON-строки. Объект клавиатуры поддерживает следующие настройки:
keyboard(массив массивов объектов KeyboardButton) — двумерная сетка кнопок. Каждый вложенный массив представляет собой один горизонтальный ряд.resize_keyboard(boolean) — по умолчаниюfalse. Если оставить его выключенным, кнопки будут огромными (высотой со стандартную клавиатуру телефона). Всегда устанавливайтеtrue, чтобы кнопки аккуратно сжимались под размер текста.one_time_keyboard(boolean) — еслиtrue, клавиатура автоматически скроется сразу после нажатия на любую кнопку. Её можно будет вернуть, нажав на специальную иконку в поле ввода.input_field_placeholder(string) — текст-подсказка, который отображается в поле ввода, когда клавиатура активна (например, «Выберите пункт меню...»). Максимум 64 символа.is_persistent(boolean) — еслиtrue, клавиатура будет отображаться всегда, даже когда открыта стандартная системная клавиатура для ввода текста.selective(boolean) — позволяет показывать клавиатуру только конкретным пользователям. Полезно в групповых чатах, чтобы не спамить интерфейс всем участникам.
Отправка Reply Keyboard на PHP
Используем функцию telegramApi(), которую мы сделали в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
// send_keyboard.php
// ID чата, куда отправляем клавиатуру.
// Значение chat_id мы научились получать в главе https://api.telegram.org/ или в разделе про webhook.
$chatId = 123456789;
// Описываем структуру клавиатуры
$keyboardMarkup = [
'keyboard' => [
[
['text' => '🛍️ Каталог'],
['text' => '🛒 Корзина']
],
[
['text' => '📱 Поделиться контактом', 'request_contact' => true],
['text' => '📍 Отправить локацию', 'request_location' => true]
],
[
['text' => '❓ Помощь']
]
],
'resize_keyboard' => true,
'one_time_keyboard' => false,
'input_field_placeholder' => 'Выберите действие...'
];
try {
$response = telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Добро пожаловать в наше меню! Используйте кнопки ниже для навигации.',
'reply_markup' => json_encode($keyboardMarkup)
]);
echo "Запрос успешно выполнен. Результат:\n";
print_r($response);
} catch (Exception $e) {
echo "Произошла ошибка: " . $e->getMessage() . "\n";
}
Анализ успешного ответа API
При успешной отправке сообщения с клавиатурой Telegram возвращает стандартный объект Message. Обратите внимание, что сама структура клавиатуры в ответе не дублируется — API лишь подтверждает факт отправки текстового сообщения:
{
"ok": true,
"result": {
"message_id": 1024,
"from": {
"id": 987654321,
"is_bot": true,
"first_name": "My Helper Bot",
"username": "my_helper_bot"
},
"chat": {
"id": 123456789,
"first_name": "Ivan",
"type": "private"
},
"date": 1672531199,
"text": "Добро пожаловать в наше меню! Используйте кнопки ниже для навигации."
}
}
Если в ответе поле ok равно false, обязательно проверяйте description. Самая частая ошибка при отправке клавиатур — невалидный JSON в параметре reply_markup (например, забыли вызвать json_encode или передали некорректную структуру массивов).
Обработка нажатий на сервере
Когда пользователь нажимает кнопку, ваш скрипт-обработчик получает обычное сообщение. Для разбора входящих обновлений мы используем логику, описанную в главе Webhook.
Чтобы увидеть структуру входящего запроса «изнутри», вы можете записать сырой поток в файл с помощью file_put_contents('update.json', file_get_contents('php://input')). Ниже представлен пример обработки текстовых кнопок, а также специальных кнопок отправки контакта и геолокации.
Используем функцию telegramApi(), которую мы сделали в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
// webhook_handler.php
$rawInput = file_get_contents('php://input');
$update = json_decode($rawInput, true);
if (isset($update['message'])) {
$message = $update['message'];
$chatId = $message['chat']['id'];
// 1. Обработка текстовых кнопок
if (isset($message['text'])) {
$text = $message['text'];
switch ($text) {
case '🛍️ Каталог':
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Загружаю актуальный список товаров...'
]);
break;
case '🛒 Корзина':
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Ваша корзина пуста. Добавьте товары из каталога.'
]);
break;
case '❓ Помощь':
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Вы можете управлять ботом с помощью кнопок меню.'
]);
break;
}
}
// 2. Обработка кнопки отправки контакта
if (isset($message['contact'])) {
$contact = $message['contact'];
$phoneNumber = $contact['phone_number'];
$firstName = $contact['first_name'];
// Безопасность: проверяем, совпадает ли user_id контакта с id отправителя,
// чтобы пользователь не прислал чужой контакт из телефонной книги.
if (isset($contact['user_id']) && $contact['user_id'] === $message['from']['id']) {
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => "Спасибо, {$firstName}! Ваш номер {$phoneNumber} успешно верифицирован."
]);
} else {
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Пожалуйста, отправьте именно свой контакт через кнопку.'
]);
}
}
// 3. Обработка кнопки отправки геолокации
if (isset($message['location'])) {
$location = $message['location'];
$latitude = $location['latitude'];
$longitude = $location['longitude'];
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => "Координаты приняты! Широта: {$latitude}, Долгота: {$longitude}"
]);
}
}
Как удалить клавиатуру
Reply Keyboard не исчезает сама по себе (даже если включен параметр one_time_keyboard, она лишь сворачивается в иконку). Чтобы полностью убрать её с экрана пользователя, необходимо отправить специальный объект ReplyKeyboardRemove в параметре reply_markup очередного сообщения.
Используем функцию telegramApi(), которую мы сделали в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.
<?php
// remove_keyboard.php
$chatId = 123456789;
$removeMarkup = [
'remove_keyboard' => true,
'selective' => false
];
try {
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Переходим в стандартный режим ввода. Клавиатура скрыта.',
'reply_markup' => json_encode($removeMarkup)
]);
echo "Клавиатура успешно удалена из интерфейса чата.\n";
} catch (Exception $e) {
echo "Ошибка: " . $e->getMessage() . "\n";
}
Важные ограничения и особенности
- Отсутствие скрытых данных: В отличие от Inline-кнопок, где есть скрытый параметр
callback_data, обычные кнопки отправляют только видимый текст. Если вы измените название кнопки (например, исправите опечатку), старый обработчик на PHP перестанет на неё реагировать. Придётся менять условия вswitch. - Проблема локализации: Если ваш бот мультиязычный, вам придётся проверять текст кнопок на всех поддерживаемых языках либо использовать FSM (конечные автоматы) для отслеживания текущего контекста пользователя.
- Перекрытие интерфейса в группах: В групповых чатах Reply Keyboard может мешать общению. Используйте параметр
selective => true, чтобы клавиатура появлялась только у того пользователя, который вызвал команду.
Дальше: Команды /start, /help