Skip to content

New Keyboard structure and how to pass dynamic arguments

Lorenzo Lapucci edited this page Jun 25, 2017 · 4 revisions

I'm currently developing a newsbot for my projects with php-telegram-bot. With the update from 0.35 to 0.36 of the php telegram bot I ran into a problem. How do I create an InlineKeyboard with ONE button per row? With 0.35 it was really easy, but the changed keyboard structure in 0.36 it was a bit tricky.

So I decide to create a little wiki entry for this and hope someone will find this helpful :)

Static definition of keyboards

In the file InlineKeyboardCommand.php it is perfectly explained how to create a static and basic keyboard with multiple buttons in one row:

$inline_keyboard = new InlineKeyboard([
    ['text' => 'inline', 'switch_inline_query' => 'true'],
    ['text' => 'callback', 'callback_data' => 'identifier'],
    ['text' => 'open url', 'url' => 'https://github.com/akalongman/php-telegram-bot'],
]);

Please note, that all buttons are wrapped together into one array. This is passed as one argument into the constructor of InlineKeyboard. Now, if you want to have button 1 into a single row, you have to pass 2 arrays as arguments to InlineKeyboard:

$inline_keyboard = new InlineKeyboard(
    [
        ['text' => 'inline', 'switch_inline_query' => 'true'],
    ],
    [
        ['text' => 'callback', 'callback_data' => 'identifier'],
        ['text' => 'open url', 'url' => 'https://github.com/akalongman/php-telegram-bot'],
    ]
);

But, this is a very static definition of a keyboard, right?

Dynamic Keyboards and how to pass it to InlineKeyboard

Lets think about following: A user is searching for news categories and your bot found more than one that fits the users search. You want to display them as a button list to the user, but the names of the categories are too long to display the buttons in the same row. I actually had exact this problem: 10 or more buttons in one row and the user has no chance to read the text of the button.

So, here we are: How do you pass a dynamic created keyboard to the class? I don't know if there is an other way, I didn't get it to work by searching for functionality to pass a keyboard after initializing the class. So I searched a way to pass the items of an array to the class. And there is a way, you do the following.

You build your array of keyboard rows:

$rows = [];
foreach($categories as $category) {
    $rows[] = [
        ['text' => $category["name"], 'callback_data' => $category["command"]]
    ];
}

And then you initiate the InlineKeyboard class like this:

$inline_keyboard = New InlineKeyboard(...$rows);

And you're done!

The tree dots before $rows is important - and only available in PHP 5.6 or higher. It's called 'splat operator' and passes all items of an array as separate arguments to the constructor of the class.

Saved my ass - and hope it'll help you too!

P.S. For PHP version before 5.6

$class = new ReflectionClass("InlineKeyboard");
$inline_keyboard = $class->newInstanceArgs($rows);