Еще раз про кнопки и клавиатуру

Очень много вопросов поступает о кнопках и клавиатуре. Как расположить несколько кнопок в несколько рядов? Как обработать событие по кнопке или клавиатуре? Несколько примеров расположения на экране интерфейса приложения Телеграм.

Очень много вопросов поступает о кнопках и клавиатуре. Как расположить несколько кнопок в несколько рядов? Как обработать событие по кнопке или клавиатуре? На сайте уже есть статья про взаимодействие пользователя и бота на основе кнопок и клавиатуры, поэтому в этой статье приведу несколько примеров их расположения на экране интерфейса приложения Телеграм.

<?php

Class Bot
{
    // Токен бота
    private $token = "TOKEN_BOT";
    // id пользователя которому бот будет отправлять примеры
    // укажите ваш id - узнать можно @myidbot
    private $userId = 0;
    // свойство в котором будем хранить переданные данные из Телеграм Бот АПИ
    private $data;

    /**
     * Bot constructor.
     */
    public function __construct()
    {
        // сохраняем данные из Телеграм Бот АПИ в свойство
        $this->data = json_decode(file_get_contents('php://input'), true);
        // запускаем роутер
        $this->router();
    }

    /** Роутер - определяет куда направлять запрос от Телеграм Бот АПИ
     * @return bool
     */
    private function router()
    {
        // проверяем на объект Message https://core.telegram.org/bots/api#message
        if (array_key_exists("message", $this->data)) {
            // если это текстовое сообщение объекта Message
            if (array_key_exists("text", $this->data['message'])) {
                // если это команда /start
                if ($this->data['message']['text'] == "/start") {
                    // вызываем метод обработки команды /start
                    $this->start();
                    // Можно отдельную кнопку клавиатуры обработать
                } elseif ($this->data['message']['text'] == "Button 1_1") {
                    $this->actionKeyboardButton();
                    // можно по регулярке проверять - сюда попадут все другие кнопки клавиатуры
                } elseif (preg_match("~^Button~", $this->data['message']['text'])) {
                    $this->actionKeyboardButton();
                } else {
                    return false;
                }
            } else {
                return false;
            }
            // если это объект СallbackQuery https://core.telegram.org/bots/api#callbackquery
        } elseif (array_key_exists("callback_query", $this->data)) {
            // получаем значение (название метода) под ключем 0 из callback_data кнопки inline
            $method = current(explode("_", $this->data['callback_query']['data']));
            // вызываем переданный метод и передаем в него весь объект callback_query
            $this->$method($this->data['callback_query']);
        } else {
            return false;
        }
    }

    /**
     * Старт бота
     */
    private function start()
    {
        // Передать в reply_markup можно, что-то одно:
        // InlineKeyboardMarkup     // выводит кнопки
        // или ReplyKeyboardMarkup  // выводит клавиатуру
        // или ReplyKeyboardRemove  // удаляет клавиатуру
        // или ForceReply           // ставит сообщение в формат Reply


        //////////////////////////
        ///
        /// InlineKeyboardMarkup - https://core.telegram.org/bots/api#inlinekeyboardmarkup
        ///
        //////////////////////////
        $buttons = json_encode([
            'inline_keyboard' => [
                [
                    [
                        // текст кнопки
                        "text" => "Test",
                        // передаем значения для обработки кнопки разделенные знаком _
                        // первым идет метод который будет обрабатывать эту кнопку
                        // в данном примере это actionInlineButton
                        // вторым параметром идет значение 1234 для примера
                        // параметров может быть много все через заранее определенный
                        // знак в этом случае это нижнее подчеркивание
                        // общая длинна всей строки не должна превышать 64 байта (символа)
                        "callback_data" => "actionInlineButton_1234"
                    ],
                    [
                        // текст кнопки
                        "text" => "Test",
                        // ссылка на ресурс
                        "url" => "http://imakebots.ru"
                    ]
                ]
            ],
        ], true);


        //////////////////////////
        ///
        /// Пример 3-х рядного расположения inline-кнопок
        ///
        //////////////////////////
//        $buttons = json_encode([
//            'inline_keyboard' => [
//                // первый ряд
//                [
//                    // первая кнопка первого ряда
//                    [
//                        "text" => "Test1_1",
//                        "callback_data" => "actionInlineButton_1234"
//                    ],
//                    // вторая кнопка первого ряда
//                    [
//                        "text" => "Test1_2",
//                        "url" => "http://imakebots.ru"
//                    ]
//                ],
//                // второй ряд
//                [
//                    // первая кнопка второго ряда
//                    [
//                        "text" => "Test2_1",
//                        "callback_data" => "actionInlineButton_1234"
//                    ],
//                    // вторая кнопка второго ряда
//                    [
//                        "text" => "Test2_2",
//                        "url" => "http://imakebots.ru"
//                    ],
//                    // третья кнопка второго ряда
//                    [
//                        "text" => "Test2_3",
//                        "url" => "http://imakebots.ru"
//                    ]
//                ],
//                // третий ряд
//                [
//                    // первая кнопка третьего ряда
//                    [
//                        "text" => "Test3_1",
//                        "callback_data" => "actionInlineButton_1234"
//                    ],
//                ]
//            ],
//        ], true);




        //////////////////////////
        ///
        /// ReplyKeyboardMarkup - https://core.telegram.org/bots/api#keyboardbutton
        ///
        //////////////////////////
//        $buttons = json_encode([
//            "keyboard" => [
//                [
//                    [
//                        // текст кнопки
//                        "text" => "Button 1",
//                        // необязательное поле: в значении true при нажатии на кнопку будет передан телефон
//                        "request_contact" => false,
//                        // необязательное поле: в значении true будет передано месторасположение
//                        "request_location" => false,
//                        // request_location и request_contact - взаимоисключающие значения
//                    ],
//                    [
//                        "text" => "Button 2",
//                    ]
//                ]
//            ],
//            // в значении true после нажатия на любую кнопку клавиатура будет скрыта,
//            // вызвать обратно можно по нажатию спец иконки в интерфейсе приложения Телеграм
//            'one_time_keyboard' => false,
//            // в случае false клавиатура всегда имеет ту же высоту, что и стандартная клавиатура приложения.
//            'resize_keyboard' => true,
//            // показывать клавиатуру только пользователю который ее вызвал, удобно для групп
//            'selective' => true,
//        ], true);

        //////////////////////////
        ///
        /// Пример 3-х рядного расположения кнопок клавиатуры
        ///
        //////////////////////////
//        $buttons = json_encode([
//            "keyboard" => [
//                // первый ряд кнопок клавиатуры
//                [
//                    // первая кнопка первого ряда клавиатуры
//                    [
//                        "text" => "Button 1_1",
//                    ],
//                    // вторая кнопка первого ряда клавиатуры
//                    [
//                        "text" => "Button 1_2",
//                    ]
//                ],
//                // второй ряд клавиатуры
//                [
//                    // первая кнопка второго ряда клавиатуры
//                    [
//                        "text" => "Button 2_1",
//                    ],
//                    // вторая кнопка второго ряда клавиатуры
//                    [
//                        "text" => "Button 2_2",
//                    ],
//                    // третья кнопка второго ряда клавиатуры
//                    [
//                        "text" => "Button 2_3",
//                    ]
//                ],
//                // третий ряд клавиатуры
//                [
//                    // первая кнопка третьего ряда клавиатуры
//                    [
//                        "text" => "Button 3_1",
//                    ],
//                ]
//            ],
//            'one_time_keyboard' => false,
//            'resize_keyboard' => true,
//            'selective' => true,
//        ], true);

        // отправляем текстовое сообщение
        $this->botApiQuery("sendMessage", [
            "chat_id" => $this->userId,
            "text" => "Test",
            "reply_markup" => $buttons
        ]);
    }

    /** Обработка Inline кнопки
     * @param $callback_data
     */
    private function actionInlineButton($callback_data)
    {
        // получаем массив из переданного параметра callback_data кнопки inline
        // разделяем по знаку _
        // под индексом 0 идет значение actionInlineButton
        // под последующим индексом 1 идет значение, которое может при создании
        // кнопки генерироваться под ваши требования, например это может быть id какого-нибудь объекта
        // значений может быть больше, но общая строка не должна превышать 64 байта
        $params = explode("_", $callback_data["data"]);

        // отправляем Уведомление
        $this->botApiQuery("answerCallbackQuery", [
            "callback_query_id" => $callback_data["id"],
            "text" => "Событие inline получено",
            "alert" => false
        ]);

        // отправляем текстовое сообщение
        $this->botApiQuery("sendMessage", [
            "chat_id" => $this->userId,
            "text" => "Параметр " . $params["1"],
        ]);
    }

    /**
     * Обработка KeyBoard кнопки
     */
    private function actionKeyboardButton()
    {
        // отправляем текстовое сообщение
        $this->botApiQuery("sendMessage", [
            "chat_id" => $this->userId,
            "text" => "Обработана кнопка " . $this->data['message']['text'],
        ]);
    }

    /** Запрос к Телеграм Bot Api
     * @param $method
     * @param array $fields
     * @return mixed
     */
    private function botApiQuery($method, $fields = array())
    {
        $ch = curl_init("https://api.telegram.org/bot" . $this->token . "/" . $method);
        curl_setopt_array($ch, array(
            CURLOPT_POST => count($fields),
            CURLOPT_POSTFIELDS => http_build_query($fields),
            CURLOPT_SSL_VERIFYPEER => 0,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_TIMEOUT => 10
        ));
        $r = json_decode(curl_exec($ch), true);
        curl_close($ch);
        return $r;
    }
}

// Вызываем класс создания объекта Бота
new Bot();
?>
5 комментариев
Авторизуйтесь через Telegram, чтобы оставить комментарий.
Откройте по ссылке или QR бот @iMakeBot, нажмите кнопку Старт/Start.
Следуйте инструкциям бота.

  • Вадим [4 года назад]

    как передать 'url' => ReplyKeyboardMarkup

  • iMakeBots [4 года назад → Вадим]

    Передать значение url в клавиатуру ReplyKeyboardMarkup вы сможете только в качестве текста на кнопке. Другие параметры только функциональные, по типу большие размеры у кнопок или маленькие, передать телефон при нажатии .... и тд

    Для того чтобы кнопка при нажатии вела на какой либо адрес - используйте другой тип кнопок - InlineKeyboardMarkup

  • .... [4 года назад]

    Здравствуйте все хорошо.

    Здесь осталось новый тип кнопки, который недавно добавлена request_poll

    Огромное спасибо за ваш труд.

  • Виктор [2 года назад]

    Доброго времени суток! Передаю клавиатуру в бота через следующий код:

    private function menuBot()
         {
            $buttons[] = [
                $this->buildKeyBoardButton("Кнопка 1"),
                $this->buildKeyBoardButton("Кнопка 2"),
                $this->buildKeyBoardButton("Кнопка 3")
                ];
            $fields1 = [
                'chat_id' => $this->admin,
                'text' => $this->helloText,
                'parse_mode' => 'html',
                'reply_markup' => $this->buildKeyBoard($buttons),
                ];
            $this->botApiQuery("sendMessage", $fields1); 
          }
    
     public function buildKeyboardButton($text, $request_contact = false, $request_location = false)
        {
            $replyMarkup = [
                'text' => $text,
                'request_contact' => $request_contact,
                'request_location' => $request_location,
            ];
            return $replyMarkup;
        }
    
        public function buildKeyBoard(array $options, $onetime = true, $resize = true, $selective = false)
        {
            $replyMarkup = [
                'keyboard' => $options,
                'one_time_keyboard' => $onetime,
                'resize_keyboard' => $resize,
                'selective' => $selective,
            ];
            $encodedMarkup = json_encode($replyMarkup, true);
            return $encodedMarkup;
        }
    
    private function botApiQuery($method, $fields = array())
        {
            $ch = curl_init('https://api.telegram.org/bot' . $this->token . '/' . $method);
            curl_setopt_array($ch, array(
                CURLOPT_POST => count($fields),
                CURLOPT_POSTFIELDS => http_build_query($fields),
                CURLOPT_SSL_VERIFYPEER => 0,
                CURLOPT_RETURNTRANSFER => 1,
                CURLOPT_TIMEOUT => 10
            ));
            $r = json_decode(curl_exec($ch), true);
            curl_close($ch);
            return $r;
        }

    Все работает. Вот только не могу понять как сделать кнопки в 2 ряда. Кто подскажет в данном вопросе?

  • iMakeBots [2 года назад → Виктор]

    1 вариант

    $buttons[][] = $this->buildKeyBoardButton("Кнопка 1 ряда");
    $buttons[][] = $this->buildKeyBoardButton("Кнопка 2 ряда");
    $buttons[][] = $this->buildKeyBoardButton("Кнопка 3 ряда");

    2 Вариант

    $buttons = [
        [
            $this->buildKeyBoardButton("Кнопка 1 ряда")
        ],
        [
            $this->buildKeyBoardButton("Кнопка 2 ряда")
        ]
    ]

    3 вариант

    $buttons[] = [
        $this->buildKeyBoardButton("Кнопка 1 ряда")
    ];
    
    $buttons[] = [
        $this->buildKeyBoardButton("Кнопка 2 ряда")
    ];