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

Discord Webhook Bundle Laravel Package

labymod/discord-webhook-bundle

A Symfony bundle for sending Discord webhook messages from your PHP application. Configure webhook endpoints, then post notifications, embeds, or alerts through an injected service, keeping Discord integration clean and framework-native.

View on GitHub
Deep Wiki
Context7

Getting Started

Re-check compatibility — the picture has changed, but not in a documented way. The package has moved to 1.0.0. A 0.x → 1.0.0 bump usually means (a) the maintainer is declaring the API stable and (b) breaking changes were allowed on the way there — but the release ships with no changelog, so neither is confirmed. Do the verification yourself before touching an existing install:

composer require labymod/discord-webhook-bundle --dry-run   # does it resolve against your Symfony?
composer show labymod/discord-webhook-bundle                 # what did it actually pull?

Then diff the two things that define the contract:

diff -ru vendor/labymod/discord-webhook-bundle/src/DependencyInjection/Configuration.php \
        path/to/your/last-known-good/Configuration.php

If you can't diff (fresh install), read Configuration.php and Resources/config/services.* end-to-end — those files are the changelog for this package. Check the bundle's composer.json for the Symfony range and whether the underlying labymod/discord-webhook constraint moved; a library bump can silently change timeout/retry behaviour.

  1. composer require labymod/discord-webhook-bundle:^1.0 — pin to the major explicitly. With Flex, LabyMod\DiscordWebhookBundle\DiscordWebhookBundle self-registers; otherwise add it to config/bundles.php. If the namespace changed in 1.0.0, Flex's recipe won't fix your config/bundles.php — expect a "class not found" there first.
  2. Read Configuration.php before the README. Still true at 1.0.0: small package, thin docs. Confirm the config alias (it may have changed) with bin/console debug:config <alias>. If the alias is rejected, bin/console config:dump-reference and grep for discord.
  3. Keep webhook URLs in .env.local / secrets, not YAML:
    # config/packages/discord_webhook.yaml
    laby_mod_discord_webhook:
        webhooks:
            ops:
                url: '%env(DISCORD_WEBHOOK_OPS)%'
    
    (Adjust keys to match the 1.0.0 Configuration class — the shape above is the common bundle idiom, not a guarantee, and this is exactly what a major bump is most likely to have renamed.)
  4. bin/console debug:container --show-private | grep -i webhook to find the service ID you actually inject — service IDs are the other thing majors rename.

First use case — make failures loud. One kernel.exception subscriber → one ops channel. It's a half-hour win, exercises the full path (config → service → HTTP → Discord), and tells you immediately whether 1.0.0's config shape matches what you wrote. Save embed formatting for later.

Implementation Patterns

Wrap the package, don't sprinkle it. Write a one-class façade (DiscordNotifierInterface with notify(Channel $channel, Message $message)) and inject that everywhere. This is unchanged by 1.0.0 and is still the highest-leverage decision: it makes the 1.0.0 upgrade itself a one-file review, and it's your seam when you eventually swap to symfony/notifier's Discord transport.

Upgrade in isolation, behind the façade. Because the changelog is empty, don't bundle the 1.0.0 bump with feature work. Upgrade the dependency, run your test suite against the faked DiscordNotifier, then do one manual smoke send to a private channel. If anything in the config tree or service wiring moved, it surfaces there and nowhere else.

Make delivery async. The underlying labymod/discord-webhook is a synchronous cURL call — in a request or Messenger handler it adds Discord's latency (and its outages) to your own. Unless the 1.0.0 diff shows a PSR-18 client was introduced (check the constructor signature of the webhook class), assume it's still blocking:

$bus->dispatch(new SendDiscordMessage($channel, $payload));

with a dedicated transport and a low --time-limit worker. Discord webhooks are limited to roughly 30 requests/minute per webhook, so a queue + throttle is not optional once you notify per-order or per-signup.

Attach to lifecycle events rather than calling from controllers. The patterns that pay off:

  • kernel.exception subscriber → error channel (dedupe by exception class + message, or you'll spam).
  • WorkerMessageFailedEvent → alert when a queue consumer dies.
  • Domain events (UserRegisteredEvent, OrderPaidEvent) → business channel.
  • Console CommandFinished / your deploy script → release notes to #deployments.

Use embeds for anything structured. Plain content is 2000 chars and wraps badly; an embed with title, color, and key/value fields renders as a card and is scannable on mobile. Build a small helper that maps your domain object to an embed (name, status, link, timestamp) so every channel gets consistent output.

Keep channel URLs in config, message content in code. Don't hardcode URLs per call site; resolve them by logical name (ops, billing, deploy) so a webhook rotation is an env change plus a restart, not a code change.

Enrich with context. APP_ENV, hostname, git SHA, and a link to the log/Kibana query turn "something failed" into something actionable. Add them once in your façade.

Gotchas and Tips

1.0.0 shipped without release notes — treat it as an unknown. Don't assume "1.0.0" means "same as the 0.x you have, but stable." The two files most likely to have changed are DependencyInjection/Configuration.php (config keys, alias) and Resources/config/services.* (service IDs). Diff them, or read them cold on a fresh install, before you trust your existing YAML.

Check whether the transitive library moved. composer show labymod/discord-webhook — if 1.0.0 bumped the underlying package, HTTP behaviour (timeouts, retry, error surfacing) may differ even though your config keys didn't. This is the most likely source of "it worked before the upgrade" surprises.

Pin the major. "labymod/discord-webhook-bundle": "^1.0" — not a floating constraint. With no changelog, you want the next release to be a deliberate composer update, not a Tuesday afternoon surprise.

The webhook URL is the credential. Anyone with it can post to the channel. Never log it, never echo it in an exception message, never commit it. Rotate by deleting the webhook in Discord — there's no auth layer to revoke.

Success is HTTP 204, not 200. A 200-shaped check silently treats every send as a failure. Discord returns 204 No Content on success, 400 on a malformed payload, 401/404 on a dead webhook, and 429 with a retry_after (seconds, float) when rate limited. Handle 429 explicitly if you're not queueing.

Empty messages are a 400. You need content and/or embeds. Same for exceeding limits: 10 embeds per message, 6000 chars total across embed fields, 4096 for a description, 256 for a title. Truncate user-derived strings.

Colors are decimal integers. 0xRRGGBB as an int, not "#ff0000".

Timestamps must be ISO 8601 ((new \DateTimeImmutable())->format(DATE_ATOM)), not a Unix timestamp.

Mentions are a footgun. If any content includes user input, @everyone or @here will ping the channel. Sanitise, or set allowed_mentions to an empty parse list in the payload.

Timeouts will bite you. Unless the 1.0.0 diff shows otherwise, assume cURL defaults — a Discord stall can hang a web request. Prefer Messenger (async), and if you must send inline, set an explicit short timeout; if the package still exposes none, send in kernel.terminate at minimum.

Testing requires your own seam. With no PSR-18/PSR-7 in play, MockHttpClient won't intercept anything. You cannot unit-test around a cURL call — fake at your DiscordNotifier interface, and reserve real HTTP for a single smoke test against a private test channel. That smoke test is now also your 1.0.0 acceptance check.

Debugging: most failures are a config-key typo (extra likely after a major) or a stale webhook (404). Inspect the raw JSON payload before blaming the library — build the payload array, json_encode it, and paste into Discord's webhook tester, or curl -i -H 'Content-Type: application/json' -d @payload.json $URL. If nothing is sent at all, debug:config and debug:container will usually reveal a misregistered service — start there when 1.0.0's alias or service ID differs from what you had.

Extension points are still thin. Expect to either replace the injected service with your own definition (alias the bundle's service ID to your class) or skip the DI layer and construct the underlying Webhook object yourself from a URL — the library is only a handful of classes, and vendoring it is a realistic response to any 1.0.0 wiring you dislike. For multi-tenant or per-database webhooks, add a compiler pass or resolve URLs at runtime in your façade; don't contort the bundle's static config.

Re-evaluate the exit, don't cancel it. A 1.0.0 with no changelog is a stability signal, not proof of maintenance. Keep the façade, keep the migration to symfony/notifier's Discord transport on the roadmap — the wrapper makes it a one-file change whichever way this goes.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console