Download the PHP package wekser/laragram without Composer

On this page you can find all versions of the php package wekser/laragram. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laragram

Laragram

A Laravel package for building Telegram bots in MVC style — routing, controllers, views, and a station-based state machine, all wired into the Laravel ecosystem.

Latest Version Tests Downloads

What's in the box: routing on event / station / role / chat type / forum topic · multi-step scenes with validation, conditional steps, back navigation and timeouts · views as message components on disk, with auto-escaping, keyboards and albums · groups & forum topics with per-(user, chat, topic) state · payments in Telegram Stars and fiat · inline mode · file upload and download · reactions · broadcasting with auto-pruning of unreachable users · a bundled admin panel with its own login · optional queue offload · a testing trait for whole bot flows without HTTP.

Contents: Commands


Installation

Publish the config and run migrations:

Add your bot credentials to .env:

Register the webhook:

laragram:install leaves you with blank route and scene files. To start from a working bot instead, publish the runnable demo — views, lang files, demo controllers, and demo routes appended to your route file (idempotent, safe to re-run):

No public URL yet? Skip the webhook and long-poll instead — same routing, same controllers:


Upgrading from 1.x

2.0 is a rewrite. Read the changelog in full before upgrading; the essentials:

Renamed classes and methods

1.x 2.0
BotRouteCollection · BotRouter Routing\RouteCollection · Routing\Router
Support\FormRequest · Support\FormResponse Http\RequestTransformer · Http\ResponseTransformer
Exceptions\BotException Exceptions\ExceptionHandler (a static utility, not an exception)
BotResponse::user() BotResponse::setUser()
BotClient::sendMessage() · getUserStatus() · isUserActive() Services\TelegramErrorHandler
config/config.php config/laragram.php

Behaviour changes to check

Database migration. The laragram_users and laragram_sessions tables gained columns. Fresh installs get them from laragram:install; an existing app needs its own migration — without thread_id the session upsert fails on every update:


How It Works

Telegram sends a POST request to /{prefix}/{secret}. Laragram authenticates the sender, resolves the user's current station (state), matches a route, and calls your controller. The controller returns one or several BotResponse objects; Laragram delivers each as an outbound Telegram Bot API call and answers the webhook with 200 OK.


Routes

Bot routes live in routes/laragram/routes.php. Use the injected $collection variable or the BotRoute facade — both are equivalent.

DSL reference:

Method Description
->get('event') Telegram update type (message, callback_query, inline_query, etc.)
->from('station') Only match when user is at this station
->contains('/cmd') Command, exact text, or {param} pattern
->role('admin') Restrict to users with a specific role
->chat('supergroup') Restrict to chat type(s) — ->inGroups() / ->inPrivate() are shortcuts
->thread(42) Restrict to forum topic(s) — see Group Chats & Forum Topics
->name('route_name') Assign a name (shown in route:list)
->call([Ctrl::class, 'method']) Controller action or closure
->fallback() Catch-all — matches anything not matched above

->group() applies a shared station, role, chat type, and forum topic to multiple routes:


Controllers

Controllers are resolved through Laravel's IoC container — constructor injection works out of the box.

BotRequest wraps the incoming update:

BotResponse builds the reply:

Text is auto-escaped for the active parse mode — do not manually escape, it will double-escape. Pass null as the format to send pre-formatted text.

Multiple messages

Return an array of responses to send several messages in reply to one update. Each is delivered as a separate Bot API call, in order:


Views

Views are directories under resources/laragram/ (dot notation → subdirectories). Each component of the message is a separate PHP file:

text.php — write plain text plus your own HTML markup (default parse mode is HTML); {{ }} escapes a value, {!! !!} emits it raw, {{-- --}} is a comment:

Static markup (<b>…</b>) renders as-is. {{ }} values are auto-escaped (safe for user data); {!! !!} values are emitted raw (use for trusted, pre-formatted content like translation strings). Variables from $data are extracted into scope, so $name works directly. $user (the authenticated User model) is also available.

A translation with placeholders is mixed-trust — __() substitutes :placeholder values without escaping them — so escape each one with e(): {!! __('laragram.order.placed', ['address' => e($address)]) !!}.

inline_keyboard.php — use global helper functions:

The full InlineKeyboardButton API is available as helpers: button(), href(), web_app(), login_url(), switch_inline(), switch_inline_chosen(), switch_inline_chosen_chat(), copy_text(), pay(), callback_game(). Each one takes optional trailing style: (primary/success/danger) and icon: (custom emoji) attributes — e.g. button('Delete', 'rm', style: 'danger') (Bot API 9.4+).

reply_keyboard.php:

Buttons may sit behind conditions — a keyboard component that adds none simply sends the message without a keyboard (a view with no content at all still throws). Since an omitted markup leaves the user's current reply keyboard in place, use remove_keyboard() to clear it.

media.php — for sendMediaGroup:

For single media, add a photo.php (or video.php, document.php, etc.) containing just the file_id or URL.

Render with:

Scaffold a new view directory:


Keyboards (programmatic)

For building keyboards in controllers without view files:

InlineKeyboard covers the full button API (switchInline(), switchInlineChosen(), switchInlineChosenChat(), loginUrl(), copyText(), pay(), callbackGame(), plus a paginate() helper); ReplyKeyboard adds one-tap requestContact() / requestLocation() / requestPoll() / requestUser() / requestChat() buttons. Every button method on both builders accepts optional trailing style: (primary/success/danger) and icon: (custom emoji) attributes — e.g. ->button('Delete', 'rm', style: 'danger') (Bot API 9.4+).


Station (State Machine)

Each user has a station — a string stored in laragram_sessions.station. Routes match only when the user is at the declared station. Use ->redirect() to move users between steps:

Debug routing in your terminal:


Group Chats & Forum Topics

The bot works in private chats and in groups/supergroups — private (1-on-1) behaviour is unchanged.

Forum topics

In a supergroup with topics enabled, a reply is sent back to the topic it came from — nothing to configure. Beyond that:

To push a notification into a topic with no incoming update to reply to, call the API directly — BotAPI is a __call() proxy, so any parameter passes straight through:

Upgrading? Per-(user, chat, topic) state adds chat_id and thread_id columns to laragram_sessions. Fresh installs get them from laragram:install; an existing app must add them, or the session upsert fails on every update — see Upgrading from 1.x.


Scenes (Wizards)

For multi-step forms — registration, an order, a survey — a scene manages the whole flow for you: it asks each step's question, validates the answer, stores it, and hands all answers to a completion handler. It's built on top of stations, but you don't wire them by hand.

Define scenes in routes/laragram/scenes.php:

Enter the scene from any route handler, and handle the result when it finishes:

More step/scene options: ->when(fn ($ctx) => …) (conditional steps), ->allowBack('/back'), ->timeout($minutes) + ->onTimeout(), ->onInvalid($view|$closure) (custom error message), and typed extractors ->expectContact()/expectLocation()/expectPhoto()/expectCallback(). A SceneContext exposes get()/all()/has()/request()/user(). Back navigation drops any answers a changed earlier answer makes irrelevant (so onComplete never sees inconsistent data), and an invalid reply re-asks the step without resetting the timeout() clock.

Scenes require the database auth driver (step state is persisted between updates in laragram_sessions.payload). Scaffold one with php artisan laragram:make:scene order --steps=size,address.

See the Scenes wiki page for the full reference.


Payments (Telegram Stars & fiat)

Send invoices, answer the checkout steps, and handle completed payments — for both Telegram Stars (XTR) and fiat currencies (Telegram Payments 2.0):


Inline Mode

Answer inline_query updates — the results users get typing @yourbot query in any chat:

Result builders: article(), photo(), gif(), video(), document(), cachedPhoto(), sticker(), and raw(array) for any other InlineQueryResult type. Answer-level options: cache(), personal(), nextOffset() (pagination), button(). The inline_query_id is injected automatically.


Files

Sending a local file or URL

BotResponse speaks JSON, so it can send media only by file_id or URL — it cannot upload bytes. MediaUploader does that in one outbound call and hands you the permanent file_id Telegram assigns:

Types: photo, document, audio, video, voice, animation, video_note, sticker. Telegram requires a destination chat even for an upload, so the media is delivered to $chatId as a side effect — use the recipient's id, or any chat the bot can reach. The source is trusted server-side input: a local path is read straight off disk, and only http/https URLs are accepted (file://, ftp://, … are rejected). Never pass unvalidated user input.

Receiving a file

Turn a file a user sent to the bot into bytes or a stored file — the mirror image of MediaUploader:

BotRequest::fileId() finds the file across the common media fields (photo → largest size, document, video, audio, voice, animation, video_note, sticker). Downloads are SSRF-hardened and size-capped:


Message Reactions

React to messages and handle users' reactions:

react() accepts an emoji string, a list of them, raw ReactionType arrays (custom emoji), or [] to clear the bot's reaction.

Telegram delivers message_reaction / message_reaction_count updates only when allowed_updates explicitly includes them — pass it when calling setWebhook.


Queue (optional, for scale)

By default Laragram processes each update inside the webhook request. Under bursts of concurrent users you can offload processing to a queue: the webhook validates the update, dispatches a job, and answers 200 OK immediately, while routing and the outbound Bot API calls run on a worker.

Enable it in .env:

Run a worker:

Use Redis in production — the rate limiter and the per-user lock need a shared cache store to be accurate across multiple workers. When disabled (the default), behaviour is fully synchronous and unchanged.


Broadcasting (mass messaging)

Send one message to your whole user base — announcements, promos, downtime notices — with the BotBroadcast facade or the laragram:broadcast command. Requires the database auth driver (there are no persisted users under array).

Three ways to compose a broadcast — all can carry full formatting, inline/reply keyboards, and media:

Method Rendered Use for
text($text) once a plain announcement
view($name, $data) per recipient (localized, $user in scope) a reusable, translated message; buttons/media come from the view's component files
message(BotResponse) once an ad-hoc rich message (keyboard/media built inline) — throws on an empty BotResponse

From the CLI:


Admin Panel

A bundled, server-rendered dashboard for your bot's user base — metrics, users & roles, sessions, and a broadcast composer. Self-contained (own routes + Blade views, no build step, no external dependencies), mounted at /laragram/admin by default. Requires the database auth driver.

The panel is protected by its own login page backed by the laragram_admins table — no host-app web auth is required, and it works in production from any IP. Run the migration (laragram:install scaffolds it), then create an account:

Browse to /laragram/admin and you'll be redirected to the login page. Passwords are hashed automatically by Models\Admin (a dedicated Authenticatable, distinct from the Telegram User), which logs in through a self-registered laragram_admin session guard — so no config/auth.php edits are needed.

Escape hatch: if you'd rather reuse your host app's own web auth, define a viewLaragram Gate ability — it overrides the login and decides access itself (a denying gate is a hard 403):

Pages: Dashboard (total/active users, new today/week, roles, active sessions) · Users (set role, activate/deactivate) · Sessions (browse, prune) · Broadcast — compose a plain-text message or pick an on-disk view (with optional JSON data) so an operator can send a fully-formatted, per-recipient-localized message with buttons/media, not just text; dry-run count or send, honouring the queue/sync path.


Observability

Laragram never lets an exception escape update processing — routing, delivery, and the queued job all funnel their errors through ExceptionHandler, which logs reportable ones and silences user-unreachable ones. That makes silently-handled failures invisible (they never reach failed_jobs). The BotExceptionHandled event is the seam for surfacing them:

Listening is optional (no listener = near-zero-cost no-op); dispatch is guarded, so a faulty listener can never break exception handling.

Network failures are retried. A call that fails before reaching Telegram — DNS, connect, TLS handshake, or a timeout during the handshake — is retried with a jittered exponential back-off (telegram.retries, default 2). Telegram API errors are never retried, and neither is an attempt whose request body already went out, so a retry can never deliver the same message twice. When the retries run out you get a TransportException; the rest of that message batch is skipped rather than burning a connect timeout each.

A recurring cURL error: SSL connection timeout (cURL errno 28) is a network problem on your server, not a bot bug — most often a blackholed IPv6 route to api.telegram.org. Compare curl -4 -o /dev/null -w '%{time_appconnect}\n' https://api.telegram.org/ with the same command without -4; if -4 is healthy, set LARAGRAM_API_IP_VERSION=4. If the hosting blocks Telegram outright, LARAGRAM_API_PROXY routes calls through a proxy.


Testing

Feature-test whole bot flows in-process — no HTTP, no Telegram. botReceives() runs the real auth → router → session → delivery pipeline against a recording API double, so assertions inspect the messages your bot actually sends:


Configuration

laragram:install publishes config/laragram.php. Everything has a working default; the keys you are most likely to touch:

Key Default Purpose
auth.driver database database persists users and sessions; array keeps a user in memory with no DB I/O
auth.session.lifetime 10080 Minutes before a session (and its station) expires
telegram.username — Your bot's @username, so /cmd@YourBot matches in groups
paths.route · paths.scenes laragram/routes · laragram/scenes File names under routes/; a subdirectory is allowed
paths.views laragram View directory under resources/
bot.languages ['en'] Locales your views are translated into
rate.max_attempts · rate.decay_seconds 60 · 60 Per-user inbound rate limit
security.verify_secret true Validate the X-Telegram-Bot-Api-Secret-Token header
telegram.retries · telegram.retry_delay 2 · 300 Retries on a network-level failure talking to Telegram, and the base back-off in ms
telegram.timeout · telegram.connect_timeout 30 · 10 Seconds for a whole API call, and for the connect + TLS handshake alone
telegram.ip_version — Pin outgoing calls to 4 or 6; set 4 when the host's IPv6 route to Telegram blackholes

Auth drivers. The database driver is the default and the one to use: it persists the User, the station, and scene state, and it is required by scenes, broadcasting, the admin panel, roles, and update deduplication. The array driver skips all database I/O — useful for a stateless bot or a fast test suite, but every user is permanently at station start.

Roles. The role column is never written by the auth drivers — assign it yourself:

Then gate routes with ->role('admin'), or check $user->hasRole('admin') / $user->isAdmin() in a handler.

See the Configuration wiki page for every key.


Artisan Commands

Command Description
laragram:install Bootstraps the host app: config, migrations, blank route/scene files, .env variables
laragram:publish Publishes the runnable demo: views, lang, demo controllers + routes (incl. Stars payments, inline mode, file receiving)
laragram:webhook:set Register the webhook with Telegram
laragram:webhook:remove Remove the webhook
laragram:getMe Display bot info (getMe)
laragram:webhook:info Display current webhook state
laragram:poll Start long-polling (dev without a public URL)
laragram:route:list List all registered bot routes
laragram:route:match {event} {text} Debug: show which route matches
laragram:session:prune Delete expired sessions
laragram:make:controller Scaffold a new bot controller
laragram:make:view Scaffold a new bot view directory
laragram:make:scene Scaffold a new scene (wizard) in the scenes file
laragram:scene:list List all registered scenes
laragram:set-role {uid} {role} Assign a role to a user
laragram:broadcast {message?} Mass-message users (--view, --data, --role=*, --include-inactive, --dry-run, --no-confirm)
laragram:admin:create {username?} Create (or reset the password of) an admin-panel login account (--name, --password)
laragram:admin:delete {username} Delete an admin-panel login account

Supported Update Types

Event Matched against
message / edited_message / channel_post / edited_channel_post text
callback_query data
inline_query query
chosen_inline_result result_id
shipping_query / pre_checkout_query invoice_payload
poll question
poll_answer option_ids
my_chat_member / chat_member / chat_join_request from
message_reaction user
message_reaction_count reactions

Changelog

See CHANGELOG for release notes.

License

MIT — see LICENSE.


All versions of laragram with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
illuminate/support Version ^12.0|^13.0
ext-curl Version *
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package wekser/laragram contains the following files

Loading the files please wait ...