Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Notification Bundle Laravel Package

xmon-org/notification-bundle

A notification bundle for PHP/Symfony apps that centralizes creating, sending, storing, and managing user notifications with pluggable channels and reusable templates.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal steps

  1. composer require xmon-org/notification-bundle:^1.5
  2. Register the bundle/provider — note this ships as a bundle (Symfony-style), so in Laravel you'll typically wire the notifier/transport services manually in a service provider rather than relying on auto-discovery.
  3. Publish/define config for the Telegram transport: bot token (from @BotFather) and a default chat_id. Keep the token in .env, never in the committed config.
  4. Send your first message: a plain text Telegram message to a known chat, then re-send with ForceReply enabled to confirm the UI prompt appears in the client.

Where to look first

  • The Telegram transport/notifier class — this is the only area touched by 1.5.0.
  • The message/DTO object that now carries a text payload and a ForceReply flag.
  • The CHANGELOG diff for c722bb8, which is small and shows exactly which options are exposed.

First use case

Transactional alerts to an ops chat (deploy finished, queue backed up, invoice failed). Plain text messages are enough here; you don't need templates or keyboards to get value on day one.

Implementation Patterns

Plain text notifications

Treat the new text support as the default channel for short, human-readable alerts. Keep payloads under Telegram's 4096-character limit and prefer a single message per event over concatenating a digest — splitting/truncation is on you, not the transport.

ForceReply for lightweight two-way flows

ForceReply is the interesting part of this release: it opens the user's client with the reply box pre-focused and quoting your message. Use it for confirmations and short prompts:

  • "Deploy to prod? Reply yes <ticket-id>" — the reply carries reply_to_message, which gives you a reliable correlation key back to the original notification.
  • Approval gates for jobs that are otherwise fire-and-forget.
  • Prompting an on-call engineer for an incident tag or acknowledgement.

Design the pattern as send → store message_id → match inbound reply on reply_to_message.message_id. ForceReply only renders the prompt; the round trip is your responsibility.

Routing and fan-out

Keep notification routing declarative (event → recipients/channels) rather than sprinkling send() calls through controllers. That way adding a second channel later doesn't touch business logic, and you can route the same event to a chat for humans and a webhook/log for machines.

Async delivery

Telegram calls are network I/O — dispatch notifications on a queue so a slow or rate-limited API never blocks a request. Pair this with a retry policy that respects retry_after from Telegram's 429 response instead of a fixed backoff.

Testing

Bind a fake/null transport in the test container and assert on the composed notification (recipient, text, ForceReply flag) rather than hitting the API. Reserve real API calls for a single manual smoke test per environment.

Gotchas and Tips

It's a bundle, not a Laravel package. This is the biggest friction point. There's no Laravel service provider, no facade, no config/notifications.php auto-merge. Expect to write a small bridge provider, resolve services from the container, and own the config loading yourself. Budget for that in your first estimate.

ForceReply does not mean "wait for a reply." The flag only affects the client UI. If you don't already have an update receiver (webhook endpoint or getUpdates poller), replies go nowhere. Confirm your inbound path exists before building an approval flow on top of this.

Rate limits are real. Roughly 30 messages/second globally and ~1 message/second per chat. Broadcast loops to many chats will hit 429s — batch, throttle, and respect retry_after.

Escaping and parse mode. If you pass parse_mode (MarkdownV2/HTML), unescaped user data will break the message or silently drop it. Escape interpolated values, or send as plain text and skip formatting until you need it.

chat_id resolution. Numeric IDs (including the -100... supergroup form) and @channelusername behave differently regarding permissions and bot membership. Prefer explicit numeric IDs in config; usernames break silently when a channel is renamed.

Secret handling. The bot token embeds the bot ID and is effectively a password. Rotate via @BotFather if it ever lands in logs — and scrub request/response logging so tokens and message bodies don't end up in your log aggregator.

Version pinning. Pin to ^1.5 and read the diff for c722bb8 before upgrading further; the Telegram transport is clearly under active development, so small releases may adjust the message-construction API.

Debugging checklist. No message delivered? In order: wrong chat_id, bot not a member/admin of the chat, token invalid or revoked, 400 from an unescaped entity, or 429 swallowed by a permissive catch block. Log the raw Telegram response body at debug level — the error descriptions are specific enough to pinpoint the cause.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route