Telegram бот PHP: от основ до продвинутых сценариев
Основные подходы к созданию Telegram бота на PHP
Разработка ботов для Telegram на PHP может быть реализована несколькими способами. Выбор зависит от окружения, навыков и требований к проекту. Рассмотрим различные варианты, их достоинства и ограничения, а также типичные сложности.
Как создать эффективного бота с помощью Guzzle?
Библиотека GuzzleHttp предоставляет удобный интерфейс для HTTP запросов и является рекомендованным инструментом при наличии Composer. Установка:
composer require guzzlehttp/guzzle
Пример класса для работы с API:
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
class TelegramBot {
private $token;
private $client;
public function __construct($token) {
$this->token = $token;
$this->client = new Client(['base_uri' => "https://api.telegram.org/bot{$token}/"]);
}
public function getUpdates() {
$response = $this->client->get('getUpdates');
return json_decode($response->getBody(), true);
}
public function sendMessage($chatId, $text) {
$response = $this->client->post('sendMessage', [
'form_params' => [
'chat_id' => $chatId,
'text' => $text
]
]);
return json_decode($response->getBody(), true);
}
}
Применение: создайте объект с токеном, получите обновления и отправьте ответ.
Типичные проблемы:
- Необходимость установки Composer и зависимостей на сервере.
- Таймауты при длительном polling (настройка timeout у Client).
- Ошибки соединения - проверьте доступность api.telegram.org.
Как реализовать бота без внешних библиотек (чистый PHP)?
Если Composer недоступен, можно использовать встроенные функции cURL. Пример отправки текстового сообщения:
$token = '123456:ABC-DEF1234';
$chatId = 123456789;
$text = 'Привет!';
$url = "https://api.telegram.org/bot{$token}/sendMessage?chat_id={$chatId}&text=" . urlencode($text);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (curl_error($ch)) {
echo 'Ошибка cURL: ' . curl_error($ch);
}
curl_close($ch);
Этот вариант проще в развертывании, но менее удобен для сложных запросов (например, с клавиатурой).
Проблемы:
- Обработка ошибок cURL вручную.
- Трудности с передачей JSON в POST запросах (нужно указывать заголовок Content-Type).
- Отсутствие автоматической десериализации ответа.
Как использовать готовые фреймворки для Telegram ботов?
Специализированные библиотеки, такие как irazasyed/telegram-bot-sdk или Longman/TelegramBot, упрощают разработку. Установка:
composer require irazasyed/telegram-bot-sdk ^2.0
Пример использования SDK:
use Telegram\Bot\Api;
$telegram = new Api('YOUR_BOT_TOKEN');
$response = $telegram->sendMessage([
'chat_id' => $chatId,
'text' => 'Hello'
]);
Библиотеки предоставляют готовые методы для команд, клавиатур и work-событий, что ускоряет разработку. Однако возможны проблемы с версиями зависимостей.
Проблемы:
- Обновления библиотек могут ломать совместимость.
- Избыточность функционала для простых ботов.
- Необходимость изучения документации.
Как настроить Webhook вместо Polling?
Webhook - более производительный метод получения обновлений. Telegram отправляет POST запрос на ваш сервер при каждом новом событии. Установка Webhook осуществляется через API:
$url = "https://yoursite.com/bot.php";
$response = file_get_contents("https://api.telegram.org/bot{$token}/setWebhook?url=$url");
Файл bot.php обрабатывает входящие данные:
$update = json_decode(file_get_contents('php://input'), true);
$chatId = $update['message']['chat']['id'] ?? null;
if ($chatId) {
// обработка
}
Webhook требует HTTPS и часто статический IP. Ошибки - неверный SSL сертификат или блокировка порта 443.
Проблемы:
- Сервер должен быть доступен из интернета с HTTPS.
- Таймауты ответа - Telegram ждет ответ не более 10 секунд.
- Сложность отладки - локально не протестировать.
Как обрабатывать команды /start и другие?
Распознавание команд - ключевая задача. Пример на чистом PHP:
$text = $update['message']['text'] ?? '';
if ($text === '/start') {
sendMessage($chatId, 'Добро пожаловать!');
} elseif (str_starts_with($text, '/echo ')) {
$msg = substr($text, 6);
sendMessage($chatId, $msg);
}
Ошибка: не учитывать регистр команды. Рекомендуется сравнивать с помощью strtolower.
Проблемы: большие боты со множеством команд - клоноводство кода. Решение - использовать шаблон Command Handler.
Итоговый выбор: Для большинства проектов оптимально использовать Guzzle (или чистый cURL при ограничениях) с Webhook. Готовые SDK хороши для крупных проектов, но требуют изучения.
Расширенные примеры программного кода
Данный раздел содержит подробные примеры для типичных сценариев Telegram бота на PHP. Каждый пример сопровождается пояснением и результатом выполнения.
Пример 1: Отправка сообщения с Inline-клавиатурой
Inline-клавиатура позволяет пользователю нажимать кнопки внутри сообщения. Код с использованием Guzzle:
$chatId = 123456789;
$text = 'Выберите действие:';
$keyboard = [
'inline_keyboard' => [
[
['text' => 'Кнопка 1', 'callback_data' => 'btn1'],
['text' => 'Кнопка 2', 'callback_data' => 'btn2']
],
[
['text' => 'Ссылка', 'url' => 'https://example.com']
]
]
];
$response = $client->post('sendMessage', [
'form_params' => [
'chat_id' => $chatId,
'text' => $text,
'reply_markup' => json_encode($keyboard)
]
]);
$result = json_decode($response->getBody(), true);
if ($result['ok']) {
echo 'Сообщение отправлено с клавиатурой';
}
// Результат: в чат отправлено сообщение с двумя inline-кнопками и одной ссылкой. // Пользователь может нажать кнопку, и Telegram пришлет callback_query с соответствующими данными.
Пример 2: Обработка Callback Query
Когда пользователь нажимает inline-кнопку, Telegram отправляет callback_query. Обработка:
$update = json_decode(file_get_contents('php://input'), true);
$callbackQuery = $update['callback_query'] ?? null;
if ($callbackQuery) {
$callbackId = $callbackQuery['id'];
$data = $callbackQuery['data'];
$chatId = $callbackQuery['message']['chat']['id'];
// Ответ на callback
$client->post('answerCallbackQuery', [
'form_params' => [
'callback_query_id' => $callbackId,
'text' => "Вы нажали: $data"
]
]);
// Можно также изменить сообщение
}
// Пользователь увидит всплывающее уведомление с текстом "Вы нажали: btn1".
Пример 3: Отправка фотографии
Для отправки изображения используется метод sendPhoto. Файл может быть загружен из URL или локально.
$chatId = 123456789;
$photoUrl = 'https://picsum.photos/400/300';
$response = $client->post('sendPhoto', [
'form_params' => [
'chat_id' => $chatId,
'photo' => $photoUrl,
'caption' => 'Случайное изображение'
]
]);
// В чат отправлена фотография с подписью.
Пример 4: Загрузка файла с сервера (multipart)
Если изображение лежит на вашем сервере, используйте multipart/form-data:
$response = $client->post('sendPhoto', [
'multipart' => [
[
'name' => 'chat_id',
'contents' => $chatId
],
[
'name' => 'photo',
'contents' => fopen('/path/to/image.jpg', 'r'),
'filename' => 'image.jpg'
]
]
]);
// Отправленный файл появится в чате.
Пример 5: Работа с ParseMode (Markdown / HTML)
Telegram поддерживает форматирование текста. Пример с HTML:
$text = '<b>Жирный текст</b> и <i>курсив</i>';
$response = $client->post('sendMessage', [
'form_params' => [
'chat_id' => $chatId,
'text' => $text,
'parse_mode' => 'HTML'
]
]);
// В чате отобразится: Жирный текст и курсив.
Пример 6: Отправка документа (PDF, ZIP)
$response = $client->post('sendDocument', [
'multipart' => [
['name' => 'chat_id', 'contents' => $chatId],
['name' => 'document', 'contents' => fopen('/path/to/file.pdf', 'r'), 'filename' => 'file.pdf']
]
]);
// Пользователь получает файл с именем file.pdf.
Пример 7: Получение информации о боте
$response = $client->get('getMe');
$result = json_decode($response->getBody(), true);
echo $result['result']['username']; // выведет username бота
// Пример вывода: MyTestBot
Пример 8: Удаление вебхука
$client->post('deleteWebhook');
// или с параметрами
$client->post('deleteWebhook', ['form_params' => ['drop_pending_updates' => true]]);
// После удаления можно переключиться на getUpdates.
Пример 9: Использование getUpdates с offset для пропуска обработанных обновлений
$offset = 0; // хранить в БД или файле
$response = $client->get('getUpdates', ['query' => ['offset' => $offset, 'timeout' => 30]]);
$updates = json_decode($response->getBody(), true)['result'];
if (!empty($updates)) {
$lastId = end($updates)['update_id'];
$offset = $lastId + 1;
// сохранить offset
foreach ($updates as $update) {
// обработка
}
}
// Каждый следующий вызов получит только новые сообщения.
Пример 10: Отправка сообщения с Reply-клавиатурой (обычной)
$keyboard = [
'keyboard' => [
['Кнопка 1', 'Кнопка 2'],
['Кнопка 3']
],
'resize_keyboard' => true,
'one_time_keyboard' => false
];
$response = $client->post('sendMessage', [
'form_params' => [
'chat_id' => $chatId,
'text' => 'Выберите кнопку:',
'reply_markup' => json_encode($keyboard)
]
]);
// Внизу экрана появится клавиатура с тремя кнопками.