Middleware
Middleware allows you to execute code before or after processing an update. This is useful for authorization, logging, state checking, and other tasks.
Basic Concepts
Section titled “Basic Concepts”Middleware Interface
Section titled “Middleware Interface”All middleware must implement the TelegramRouteMiddlewareInterface interface:
use HybridGram\Core\Middleware\TelegramRouteMiddlewareInterface;use Phptg\BotApi\Type\Update\Update;
class MyMiddleware implements TelegramRouteMiddlewareInterface{ public function handle(Update $update, \Closure $next): mixed { // Code before processing
$result = $next($update);
// Code after processing
return $result; }}Built-in Middleware
Section titled “Built-in Middleware”AuthTelegramRouteMiddleware
Section titled “AuthTelegramRouteMiddleware”Automatically authorizes users through Telegram Guard:
use HybridGram\Http\Middlewares\AuthTelegramRouteMiddleware;
TelegramRouter::forBot('main') ->onCommand('/profile', function(CommandData $data) { // User is already authorized $user = Auth::user(); }) ->middleware(AuthTelegramRouteMiddleware::class);SetStateTelegramRouteMiddleware
Section titled “SetStateTelegramRouteMiddleware”Sets state after handler execution:
use HybridGram\Http\Middlewares\SetStateTelegramRouteMiddleware;
TelegramRouter::onCommand('/start', function(CommandData $data) { // ...})->middleware(new SetStateTelegramRouteMiddleware( newState: 'main_menu', useUserState: false, // Use chat state (default) ttl: 3600, // Lifetime in seconds (optional) data: ['step' => 1] // Additional data (optional)));CheckStateTelegramRouteMiddleware
Section titled “CheckStateTelegramRouteMiddleware”Checks if chat/user is in a specific state:
use HybridGram\Http\Middlewares\CheckStateTelegramRouteMiddleware;
TelegramRouter::onTextMessage(function(TextMessageData $data) { // This route triggers only if chat is in 'awaiting_input' state})->middleware(new CheckStateTelegramRouteMiddleware( requiredStates: ['awaiting_input'], useUserState: false, // Check chat state exceptMode: false // false = only if IN state, true = only if NOT in state));Example with state exclusion:
// Route triggers only if NOT in 'processing' or 'awaiting' statesTelegramRouter::onCommand('/cancel', function(CommandData $data) { // ...})->middleware(new CheckStateTelegramRouteMiddleware( requiredStates: ['processing', 'awaiting'], exceptMode: true // Exclusion mode));RateLimitTelegramRouteMiddleware
Section titled “RateLimitTelegramRouteMiddleware”Limits request frequency from user:
use HybridGram\Http\Middlewares\RateLimitTelegramRouteMiddleware;
TelegramRouter::onTextMessage(function(TextMessageData $data) { // ...})->middleware(new RateLimitTelegramRouteMiddleware( maxAttempts: 10, decayMinutes: 1));SetLocaleTelegramRouteMiddleware
Section titled “SetLocaleTelegramRouteMiddleware”Automatically sets Laravel locale based on Telegram user language:
use HybridGram\Http\Middlewares\SetLocaleTelegramRouteMiddleware;
TelegramRouter::forBot('main') ->onCommand('/start', function(CommandData $data) { // Locale is already set based on user language return __('welcome_message'); }) ->middleware(new SetLocaleTelegramRouteMiddleware( supportedLocales: ['en', 'ru', 'uk', 'pt'], fallbackLocale: 'en' ));Custom Locale Resolution
Section titled “Custom Locale Resolution”You can provide custom logic for determining the locale using the userLocale parameter:
Using a Closure:
use HybridGram\Http\Middlewares\SetLocaleTelegramRouteMiddleware;use Phptg\BotApi\Type\Update\Update;
// Determine locale from user database settingsTelegramRouter::forBot('main') ->onCommand('/start', function(CommandData $data) { return __('welcome_message'); }) ->middleware(new SetLocaleTelegramRouteMiddleware( supportedLocales: ['en', 'ru', 'uk', 'pt'], fallbackLocale: 'en', userLocale: function(Update $update): ?string { $user = UpdateHelper::getUserFromUpdate($update); if (!$user) { return null; }
// Fetch locale from your database $userModel = User::where('telegram_id', $user->id)->first(); return $userModel?->preferred_locale; } ));Using a static string:
// Force a specific locale for all users in this routeTelegramRouter::onCommand('/en_only', function(CommandData $data) { // Always in English})->middleware(new SetLocaleTelegramRouteMiddleware( userLocale: 'en'));Using Middleware
Section titled “Using Middleware”For Single Route
Section titled “For Single Route”TelegramRouter::onCommand('/admin', function(CommandData $data) { // ...})->middleware(AuthTelegramRouteMiddleware::class);Multiple Middleware
Section titled “Multiple Middleware”TelegramRouter::onCommand('/admin', function(CommandData $data) { // ...})->middleware([ AuthTelegramRouteMiddleware::class, new RateLimitTelegramRouteMiddleware(maxAttempts: 5, decayMinutes: 1),]);In Route Groups
Section titled “In Route Groups”TelegramRouter::group([ 'botId' => 'main', 'middlewares' => [ AuthTelegramRouteMiddleware::class, LoggingTelegramRouteMiddleware::class, ],], function($router) { $router->onCommand('/admin', function(CommandData $data) { // Both middleware will be applied });
$router->onCommand('/settings', function(CommandData $data) { // Both middleware will be applied });});Creating Custom Middleware
Section titled “Creating Custom Middleware”Example: Admin Permission Check
Section titled “Example: Admin Permission Check”<?php
namespace App\Telegram\Middleware;
use HybridGram\Core\Middleware\TelegramRouteMiddlewareInterface;use HybridGram\Core\UpdateHelper;use Phptg\BotApi\Type\Update\Update;
class AdminMiddleware implements TelegramRouteMiddlewareInterface{ public function handle(Update $update, \Closure $next): mixed { $user = UpdateHelper::getUserFromUpdate($update);
if (!$user || !$this->isAdmin($user->id)) { $telegram = app(\HybridGram\Telegram\TelegramBotApi::class); $chat = UpdateHelper::getChatFromUpdate($update);
if ($chat) { $telegram->sendMessage( $chat->id, '❌ You do not have permission to execute this command' ); }
return null; // Stop execution }
return $next($update); }
private function isAdmin(int $userId): bool { // Your validation logic return in_array($userId, config('telegram.admins', [])); }}Usage:
use App\Telegram\Middleware\AdminMiddleware;
TelegramRouter::onCommand('/admin', function(CommandData $data) { // Access only for admins})->middleware(AdminMiddleware::class);Global Middleware
Section titled “Global Middleware”You can register global middleware in TelegramServiceProvider:
// In boot() method of your ServiceProviderpublic function boot(): void{ $middlewareManager = app(\HybridGram\Core\Middleware\MiddlewareManager::class);
$middlewareManager->addGlobalMiddleware( LoggingTelegramRouteMiddleware::class );}Global middleware applies to all routes.
Execution Order
Section titled “Execution Order”Middleware executes in the following order:
- Global middleware (in registration order)
- Route group middleware
- Specific route middleware
Each middleware can:
- Continue execution (
return $next($update)) - Stop execution (
return null) - Modify data (pass modified Update)
What’s Next?
Section titled “What’s Next?”- States — managing chat and user states
- Sending Messages — working with TelegramBotApi