PHP code example of wekser / laragram

1. Go to this page and download the library: Download wekser/laragram library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

wekser / laragram example snippets


Schema::table('laragram_users', function (Blueprint $table) {
    $table->string('role')->default('user')->after('settings')->index();
    $table->boolean('is_active')->default(true)->after('role')->index();
    $table->timestamp('deactivated_at')->nullable()->after('is_active');
});

Schema::table('laragram_sessions', function (Blueprint $table) {
    $table->bigInteger('chat_id')->nullable()->after('user_id');
    $table->unsignedBigInteger('thread_id')->default(0)->after('chat_id');
});

// Existing rows are private chats: the chat is the user.
DB::table('laragram_sessions')
    ->join('laragram_users', 'laragram_users.id', '=', 'laragram_sessions.user_id')
    ->update(['laragram_sessions.chat_id' => DB::raw('laragram_users.uid')]);

Schema::table('laragram_sessions', function (Blueprint $table) {
    $table->unique(['user_id', 'chat_id', 'thread_id']);
    $table->index(['user_id', 'chat_id', 'thread_id', 'last_activity']);
});

use Wekser\Laragram\Facades\BotRoute;

// Match /start from any station
BotRoute::get('message')
    ->contains('/start')
    ->call([StartController::class, 'index']);

// Match any text when user is at 'ask_name' station
BotRoute::get('message')
    ->from('ask_name')
    ->call([OnboardingController::class, 'saveName']);

// Match callback with a named param, admin only
BotRoute::get('callback_query')
    ->from('home')
    ->contains('/action {id}')
    ->role('admin')
    ->call([AdminController::class, 'action']);

// Catch-all fallback
BotRoute::fallback()->call([StartController::class, 'fallback']);

BotRoute::group(function ($c) {
    $c->get('message')->contains('/users')->call([AdminController::class, 'users']);
    $c->get('callback_query')->call([AdminController::class, 'callback']);
}, from: 'admin_panel', roles: 'admin');

use Wekser\Laragram\BotRequest;
use Wekser\Laragram\BotResponse;
use Wekser\Laragram\Models\User;

class StartController extends Controller
{
    public function __construct(protected BotResponse $response) {}

    public function index(BotRequest $request, User $user): BotResponse
    {
        return $this->response
            ->text("Hello, {$user->first_name}!")
            ->redirect('home');
    }
}

$request->get('text');          // dot-notation access to any update field
$request->input('id');          // named {param} from the matched route pattern
$request->message();            // the message sub-object
$request->callbackQuery();      // the callback_query sub-object
$request->validate([...]);      // Laravel validation on the update payload

$response->text('Hello!')                          // sendMessage (HTML by default)
$response->text('Hello!', 'MarkdownV2')            // MarkdownV2 parse mode
$response->text('Hello!', null)                    // no escaping
$response->view('welcome', ['name' => 'Alice'])    // render a view directory
$response->photo($fileId, caption: 'A photo')      // sendPhoto
$response->document($fileId)                       // sendDocument
$response->edit('Updated text')                    // editMessageText
$response->answer('Done!', showAlert: true)        // answerCallbackQuery
$response->delete()                                // deleteMessage
$response->react('👍')                             // setMessageReaction
$response->action('typing')                        // sendChatAction
$response->invoice(Invoice::make()...)             // sendInvoice (see Payments)
$response->inlineResults(InlineResults::make()...) // answerInlineQuery (see Inline Mode)
$response->keyboard([...])                         // attach reply_markup (call after content)
$response->thread(42)                              // send into a forum topic (see Group Chats)
$response->redirect('next_station')                // move user to a new station

public function welcome(): array
{
    return [
        $this->response->view('greeting'),
        $this->response->text('Here is a quick tip 👇'),
        $this->response->photo($fileId, caption: 'And a picture')->redirect('home'),
    ];
}

button('Click me', 'action_1');
href('Open site', 'https://example.com');
web_app('Open Mini App', 'https://example.com/app');
row();
button('Row 2', 'action_2');

resize();
reply('Option A'); reply('Option B');
row(); reply('Help');
remove_keyboard();   // in an else branch: clear the keyboard on screen

photo($data['photo_id'], caption: 'First');
video($data['video_id']);

$response->view('welcome', ['first_name' => $user->first_name]);

use Wekser\Laragram\Telegram\Keyboards\InlineKeyboard;
use Wekser\Laragram\Telegram\Keyboards\ReplyKeyboard;
use Wekser\Laragram\Telegram\Keyboards\ForceReply;

$response->text('Choose:')->keyboard(
    InlineKeyboard::make()
        ->button('Yes', 'confirm')
        ->button('No', 'cancel')
        ->row()
        ->href('Open site', 'https://example.com')
        ->webApp('Open Mini App', 'https://example.com/app')
        ->toArray()
);

$response->text('Choose:')->keyboard(
    ReplyKeyboard::make()
        ->button('Option A')->button('Option B')
        ->row()
        ->requestLocation('📍 Send my location')   // also requestContact / requestPoll / requestUser / requestChat
        ->resize()->oneTime()
        ->toArray()
);

ReplyKeyboard::remove();   // ['remove_keyboard' => true]
ForceReply::make()->placeholder('Type here…')->toArray();

// routes/laragram/routes.php
BotRoute::get('message')->contains('/start')->call([Ctrl::class, 'start']);
BotRoute::get('message')->from('ask_name')->call([Ctrl::class, 'saveName']);
BotRoute::get('message')->from('ask_email')->call([Ctrl::class, 'saveEmail']);

// controller
public function start(): array
{
    // Send several messages at once; the next station comes from the last
    // response that calls redirect() (here, the question).
    return [
        $this->response->text('Welcome! 👋'),
        $this->response->text("What's your name?")->redirect('ask_name'),
    ];
}

public function saveName(BotRequest $request): BotResponse
{
    // store name ...
    return $this->response->text('Now your email:')->redirect('ask_email');
}

// Restrict routes to a chat type (default: any)
BotRoute::get('message')->contains('/rules')->inGroups()->call([Ctrl::class, 'rules']);
BotRoute::get('message')->contains('/settings')->inPrivate()->call([Ctrl::class, 'settings']);
BotRoute::get('message')->contains('/kick')->chat('supergroup')->call([Ctrl::class, 'kick']);

// Inspect the chat in a handler
public function rules(BotRequest $request): BotResponse
{
    $request->isGroup();       // group || supergroup
    $request->isPrivate();
    $request->chatType();      // 'private' | 'group' | 'supergroup' | 'channel'
    return $this->response->view('rules');
}

// Restrict a route to one or more topics
BotRoute::get('message')->contains('/deploy')->thread(42)->call([OpsController::class, 'deploy']);

public function deploy(BotRequest $request): array
{
    $request->threadId();          // 42 — the topic, or null outside one
    $request->isTopicMessage();

    return [
        $this->response->text('Deploying…'),                 // → back into topic 42
        $this->response->text('Logged')->thread(7),           // → into topic 7 instead
        $this->response->text('Announcement')->thread(null),  // → the General topic
    ];
}

BotAPI::sendMessage(['chat_id' => -1001234567890, 'message_thread_id' => 42, 'text' => 'Build failed']);

use Wekser\Laragram\Facades\BotResponse;
use Wekser\Laragram\Facades\BotScene;
use Wekser\Laragram\Telegram\Keyboards\InlineKeyboard;

BotScene::define('order')
    ->step('size')
        ->ask(fn ($ctx) => BotResponse::text('What size?')->keyboard(   // pick by tapping
            InlineKeyboard::make()
                ->button('Small', 'Small')->button('Medium', 'Medium')->button('Large', 'Large')
                ->toArray()))
        ->expectCallback()                                             // read the tapped button
        ->rules(['

public function order(BotRequest $request)
{
    return BotScene::enter('order');        // sends the first question
}

public function place(SceneContext $ctx)    // onComplete handler — gets every answer
{
    Order::create($ctx->all());
    return BotResponse::view('order.done')->redirect('home');
}

use Wekser\Laragram\Telegram\Payments\Invoice;
use Wekser\Laragram\Telegram\Keyboards\InlineKeyboard;

// 1. Send a Stars invoice — chat_id is injected automatically
public function donate()
{
    return $this->response->invoice(
        Invoice::make()->title('Support us')->description('One-time donation')
            ->payload('donate_1')->stars(100, 'Donation')
    )->keyboard(InlineKeyboard::make()->pay('Pay ⭐100')->toArray());
}

// Fiat variant: ->currency('USD')->price('Item', 1999)->providerToken(...)

// 2. Approve (or decline) the pre-checkout step — answer within 10 seconds
BotRoute::get('pre_checkout_query')->call(fn () => BotResponse::approveCheckout());

// 3. Handle the completed payment (a field on a "message" update — note the listener override)
BotRoute::get('message', 'successful_payment')->call([ShopController::class, 'paid']);

use Wekser\Laragram\Telegram\Inline\InlineResults;

BotRoute::get('inline_query')->call(function (BotRequest $request) {
    return BotResponse::inlineResults(
        InlineResults::make()
            ->article('1', 'Say hello', 'Hello there!')       // sends text when picked
            ->photo('2', 'https://example.com/pic.jpg')
            ->cachedPhoto('3', $fileId)                        // by cached file_id
            ->cache(300)->personal()
    );
});

// Optional: know which result the user picked (enable inline feedback with @BotFather)
BotRoute::get('chosen_inline_result')->call([StatsController::class, 'picked']);

use Wekser\Laragram\Services\MediaUploader;

public function send(MediaUploader $uploader, User $user): BotResponse
{
    // Uploads to $chatId and returns the file_id — cache it, then reuse it for free.
    $fileId = $uploader->upload('photo', storage_path('app/banner.jpg'), $user->uid);
    $fileId = $uploader->upload('document', 'https://example.com/report.pdf', $user->uid);

    return $this->response->photo($fileId, caption: 'Here you go');
}

use Wekser\Laragram\Services\MediaDownloader;

public function receive(BotRequest $request, MediaDownloader $downloader)
{
    // Fluent handle off the request (null when the update carries no file):
    $path  = $request->file()?->save('local', 'inbox/receipt.jpg');   // store on a disk
    $bytes = $request->file()?->bytes();                              // raw bytes

    // Or the service directly:
    $path = $downloader->save($request->fileId(), 's3', 'kyc/doc.pdf');

    return $this->response->text('Got it!');
}

// React to an incoming message (chat_id + message_id injected automatically)
BotRoute::get('message')->contains('/like')
    ->call(fn () => BotResponse::react('👍', big: true));

// Handle a user changing their reaction on a message
BotRoute::get('message_reaction')->call(function (BotRequest $request) {
    $reaction = $request->messageReaction();   // chat, message_id, user, old/new_reaction
    return BotResponse::react('❤️');           // react back on the same message
});

use Wekser\Laragram\Facades\BotBroadcast;
use Wekser\Laragram\Facades\BotResponse;
use Wekser\Laragram\Telegram\Keyboards\InlineKeyboard;

// Raw text to every active user
BotBroadcast::text('We are back online!')->send();

// A view, rendered per recipient (in their own language, with $user in scope)
BotBroadcast::view('news.release', ['version' => '2.0'])
    ->role(['admin', 'moderator'])     // optional: restrict to roles
    ->

// app/Providers/AppServiceProvider.php
Gate::define('viewLaragram', fn ($user) => $user->isAdmin());

use Illuminate\Support\Facades\Event;
use Wekser\Laragram\Events\BotExceptionHandled;

Event::listen(function (BotExceptionHandled $e) {
    // $e->exception, $e->reportable (was it logged?), $e->terminal (user unreachable?)
    if ($e->terminal) {
        // e.g. count how many users blocked the bot
    }
    // push to Sentry / StatsD / Horizon tags…
});

use Wekser\Laragram\Testing\BotUpdateFactory;
use Wekser\Laragram\Testing\InteractsWithBot;

class StartCommandTest extends TestCase
{
    use InteractsWithBot;

    public function test_start_greets_and_moves_to_home(): void
    {
        $this->botReceives(BotUpdateFactory::message('/start'));

        $this->assertBotRepliedWith('sendMessage');
        $this->assertBotRepliedText('Welcome');
        $this->assertUserRedirectedTo('home');
    }

    public function test_order_wizard_collects_the_size(): void
    {
        $this->botReceives(BotUpdateFactory::message('/order'));
        $this->botReceives(BotUpdateFactory::callbackQuery('Medium'));

        $this->assertInScene('order');
        $this->assertSceneData('size', 'Medium');
        $this->assertSceneStep('address');
    }
}
bash
php artisan laragram:install
php artisan migrate
bash
php artisan laragram:webhook:set
bash
php artisan laragram:publish
bash
php artisan laragram:poll

resources/laragram/
└── welcome/
    ├── text.php               ← message text — use {{ expr }} for dynamic values
    ├── inline_keyboard.php    ← call button() / href() / row()
    └── reply_keyboard.php     ← call reply() / row() / resize() / one_time()
bash
php artisan laragram:make:view welcome
bash
php artisan laragram:route:match message "/start"
php artisan laragram:route:match message "hello" --station=ask_name
bash
php artisan queue:work --queue=default
bash
php artisan laragram:broadcast "We are back online!"             # text to all active users
php artisan laragram:broadcast --view=news.release              # render a view per recipient
php artisan laragram:broadcast --view=news.release --data='{"version":"2.0"}'   # + template data (JSON)
php artisan laragram:broadcast "Admins only" --role=admin --dry-run   # just print the recipient count
bash
php artisan laragram:admin:create            # prompts for username + password (min 8 chars)
php artisan laragram:admin:create alice --name="Alice" --password=secret123   # or non-interactively
php artisan laragram:admin:delete alice      # remove an account
bash
php artisan laragram:set-role 123456789 admin