orukusaki/slackbundle
Symfony bundle for integrating Slack notifications into PHP applications. Configure incoming webhooks and send formatted messages to Slack channels through a simple service, making it easy to add alerts and updates to your projects.
Reality check first: orukusaki/slackbundle is a Symfony2 bundle, not a Laravel package. There is no SlackServiceProvider, no facade alias, and no config/slack.php. Everything in it is built around Symfony's DI container, AppKernel::registerBundles(), and the slack: configuration tree — none of which exist in Laravel. You will not be able to composer require it and start calling Slack::send().
That said, the useful part of the package is the thin client wrapper and the configuration shape it teaches. Here's how to actually get value from it in a Laravel codebase.
README.md — usage example (usually 5–10 lines, that's the whole API surface)DependencyInjection/Configuration.php — the real config schema (token, webhook URL, default channel, username, icon)Resources/config/services.xml — the service ID and class you'd be injectingSlackBundle.php — usually empty in bundles this sizemaknz/slack (incoming webhook client) or hand-roll a Guzzle call to https://hooks.slack.com/services/.... In Laravel you should install that underlying library directly:
composer require maknz/slack
(It is archived but stable and tiny; the alternative is laravel/slack-notification-channel, which is the modern, first-party answer.)php: >=5.5 / symfony/symfony: ~2.3|~2.7. On a modern Laravel (PHP 8.2+) Composer will refuse or you'll get deprecation spam.// config/services.php
'slack' => [
'webhook' => env('SLACK_WEBHOOK_URL'),
'channel' => env('SLACK_CHANNEL', '#general'),
'username' => env('SLACK_USERNAME', 'Laravel'),
],
// app/Support/SlackNotifier.php
class SlackNotifier
{
public function send(string $text, ?string $channel = null): void
{
(new \Maknz\Slack\Client(config('services.slack.webhook')))
->to($channel ?? config('services.slack.channel'))
->from(config('services.slack.username'))
->send($text);
}
}
If you are genuinely on a Symfony2 app (rare but possible), then: composer require orukusaki/slackbundle, add it to registerBundles(), add a slack: block to config.yml, and inject the slack service. That's the entire onboarding.
Bind it as a singleton, not a helper. If you choose to reuse the bundle's client class directly (vendoring the one class is often easier than fighting its Symfony wiring), wrap it in a service provider so you have one place to swap implementations:
// app/Providers/SlackServiceProvider.php
public function register(): void
{
$this->app->singleton(SlackNotifier::class, fn () =>
new SlackNotifier(config('services.slack.webhook'))
);
}
Environment-based channel routing. This is where a Slack integration earns its keep. Don't hardcode #general:
'channel' => match (app()->environment()) {
'production' => '#ops-alerts',
'staging' => '#staging-builds',
default => '#dev-sandbox',
},
Exception handler hook. The classic day-to-day use — mirror logged errors into a channel. Keep it throttled (see Gotchas) so a loop of 500s doesn't spam 400 messages:
public function report(Throwable $e): void
{
parent::report($e);
if ($this->shouldReport($e) && app()->isProduction()) {
rescue(fn () => app(SlackNotifier::class)->send(
":rotating_light: `".get_class($e)."` — ".Str::limit($e->getMessage(), 200)
));
}
}
Queue it. HTTP-to-Slack inside a request is a latency and failure vector. A tiny job keeps the request path clean and gives you retries:
class NotifySlack implements ShouldQueue
{
public int $tries = 3;
public function backoff(): array { return [5, 15, 60]; }
public function __construct(public string $text, public ?string $channel = null) {}
public function handle(SlackNotifier $slack): void
{
$slack->send($this->text, $this->channel);
}
}
Per-domain notifier methods. Rather than passing raw strings from controllers, expose intent:
public function orderFailed(Order $order): void
{
$this->send(sprintf(
":x: Order #%d failed for *%s* (<%s|view>)",
$order->id, $order->customer->name, url("/admin/orders/{$order->id}")
), '#commerce');
}
This is the pattern that pays off — the bundle's own API (a webhook POST with text, channel, username, icon_emoji, attachments) is thin enough that a 40-line wrapper around it gives you everything the bundle offered anyway.
If you truly need the Symfony bundle (you have a legacy Symfony2 sidecar or want the bundle's service in a Laravel-adjacent app): you'd have to bootstrap the Symfony DI container, register the bundle, and pull $container->get('slack'). In practice this means more code than reimplementing the call.
composer extra.laravel, don't register auto-discovery, and their dependency constraints will usually block installation on modern PHP. Expect to either fork the single client class or copy it.slack.com/api/* and can do everything. This bundle almost certainly wraps the webhook path (that's what was popular in the Symfony2 era). If you need to read or look up, you need a different tool.200 from hooks.slack.com with body invalid_payload or channel_not_found is a failure. Always inspect the response body, not just isSuccessful. The underlying clients mostly hide this — wrap it yourself if it matters.#name; DMs take @username; private groups cannot be addressed by name — you must use the channel ID (C0…/G0…) obtained from the API. This trips people up when they move from a public alerting channel to a private one.RateLimiter::attempt():
RateLimiter::attempt('slack-alerts', 1, fn () => $notifier->send($text), 10);
register() or boot(), from a global middleware, or from config:cache. It makes artisan commands (including queue:work and migrate) hang or fail when the network is down.link_names and escaping. Slack does not auto-link @user or #channel inside a plain text payload unless link_names: true is set, and &, <, > must be HTML-escaped (&, <, >). If you're interpolating user-entered strings, escape them or Slack will mangle the message or drop it.#bot-test channel, one webhook, and always point local/CI at it. Don't try to fake the HTTP call in a way that hides payload-shape bugs — that's exactly where Slack's API differs.slack) is the seam. Decorate or swap it in services.xml to replace the client without touching call sites. In Laravel, the equivalent seam is the container binding on SlackNotifier — bind an interface and you can swap webhook for API, or for a null logger in tests.laravel/slack-notification-channel is the supported path and covers attachments, blocks, and queued notifications out of the box.How can I help you explore Laravel packages today?