symfony/discord-notifier
Symfony Notifier bridge for Discord. Send chat notifications via webhook or bot using a DSN, and customize messages with DiscordOptions and rich embeds (fields, thumbnails, footers, media).
Install Dependencies:
composer require symfony/notifier symfony/discord-notifier
For Laravel-specific convenience, also consider:
composer require spatie/laravel-notification-channels-discord
Configure DSN in .env:
# Webhook mode (recommended for alerts)
DISCORD_DSN=discord://WEBHOOK_TOKEN@default?webhook_id=WEBHOOK_ID
# Bot mode (for interactive features)
DISCORD_DSN=discord+bot://BOT_TOKEN@default
First Notification (Laravel Notifications):
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Bridge\Discord\DiscordOptions;
use Symfony\Component\Notifier\Message\ChatMessage;
// Initialize Notifier (Symfony)
$notifier = new Notifier([
new DiscordTransport('discord://TOKEN@default'),
]);
// Send a simple message
$message = new ChatMessage('Deployment started!');
$notifier->send($message);
Laravel Alternative (Using Spatie):
use App\Notifications\DiscordNotification;
use Illuminate\Support\Facades\Notification;
Notification::route('discord', 'WEBHOOK_URL')
->notify(new DiscordNotification('Hello from Laravel!'));
// Using Symfony Notifier (raw)
$options = (new DiscordOptions())
->username('CI/CD Bot')
->addEmbed((new DiscordEmbed())
->title('Deployment Failed')
->color('red')
->description('Pipeline: `main` branch')
->addField((new DiscordFieldEmbedObject())
->name('Error')
->value('`Failed to compile assets`')
->inline(false)
)
->footer((new DiscordFooterEmbedObject())
->text('Check logs at example.com/pipelines/123')
)
);
$message = new ChatMessage('Build failed!');
$message->options($options);
$notifier->send($message);
| Transport | Use Case | Example DSN | Laravel Integration Notes |
|---|---|---|---|
DiscordTransport |
Webhook-based alerts (stateless) | discord://TOKEN@default |
Works with Spatie’s DiscordChannel |
DiscordBotTransport |
Bot interactions (stateful) | discord+bot://TOKEN@default |
Requires manual Symfony Notifier setup |
Laravel Workflow:
// Register transport in Laravel (Symfony Notifier)
$notifier = new Notifier([
new DiscordTransport(config('services.discord.webhook_dsn')),
new DiscordBotTransport(config('services.discord.bot_dsn')),
]);
Pattern: Dynamic Embeds from Database
use App\Models\Incident;
$incident = Incident::find(1);
$embed = (new DiscordEmbed())
->title($incident->title)
->color($incident->severity === 'critical' ? 'red' : 'yellow')
->description($incident->description)
->addField((new DiscordFieldEmbedObject())
->name('Status')
->value($incident->status)
->inline(true)
)
->addField((new DiscordFieldEmbedObject())
->name('Assignee')
->value($incident->assignee->name)
->inline(true)
)
->timestamp(new \DateTime($incident->created_at))
->footer((new DiscordFooterEmbedObject())
->text('Incident #'.$incident->id)
);
Pattern: Reusable Embed Builder
class DiscordEmbedBuilder
{
public static function alert(string $title, string $message, string $color = 'blue'): DiscordEmbed
{
return (new DiscordEmbed())
->title($title)
->color($color)
->description($message)
->footer((new DiscordFooterEmbedObject())
->text('Alert System')
->iconUrl('https://example.com/logo.png')
);
}
}
Extend Laravel’s Mailable or Notification:
use Illuminate\Notifications\Notification;
use Symfony\Component\Notifier\Message\ChatMessage;
class DiscordAlertNotification extends Notification
{
public function via($notifiable)
{
return ['discord'];
}
public function toDiscord($notifiable)
{
$message = new ChatMessage('New alert!');
$message->options((new DiscordOptions())
->addEmbed(DiscordEmbedBuilder::alert(
'Server Overload',
'CPU usage at 99% for 5 minutes',
'red'
))
);
return $message;
}
}
Dispatch in Controller:
use App\Notifications\DiscordAlertNotification;
Notification::send(
new User, // Notifiable model
new DiscordAlertNotification()
);
Symfony Notifier Limitation:
$notifier = new Notifier([new DiscordTransport($dsn)]);
dispatch(function () use ($notifier, $message) {
$notifier->send($message);
})->onQueue('discord');
Notification::route('discord', 'WEBHOOK_URL')
->notify(new DiscordNotification())
->delay(now()->addMinutes(5)); // Laravel’s queue delay
Symfony Notifier’s Failure Handling:
$notifier = new Notifier([
new DiscordTransport($dsn),
], [
new FailedTransportNotification(), // Symfony’s built-in
]);
Laravel-Specific:
// Override Symfony’s failure handler
$notifier = new Notifier([
new DiscordTransport($dsn),
], [
new class implements FailureHandlerInterface {
public function __invoke(Failure $failure): void
{
Log::error('Discord notification failed', [
'exception' => $failure->getException(),
'message' => $failure->getMessage(),
]);
}
},
]);
DSN Format Errors:
discord://TOKEN (missing @default)discord://TOKEN@default or discord://TOKEN@default?webhook_id=IDDiscordTransport::getDsn().Bot vs. Webhook:
Environment Variables:
.env never in code:
DISCORD_WEBHOOK_TOKEN=your_token_here
DISCORD_WEBHOOK_ID=your_webhook_id
DISCORD_DSN=discord://${DISCORD_WEBHOOK_TOKEN}@default?webhook_id=${DISCORD_WEBHOOK_ID}
'#FF0000' or 'red' as alias).
DiscordEmbed::color('red') for named colors.Example: Handling Long Text
$longText = str_repeat('a', 2000); // Exceeds limit
$fields = [];
for ($i = 0; $i < strlen($longText); $i += 1000) {
$fields[] = (new DiscordFieldEmbedObject())
->name('Chunk '.($i/1000 + 1))
->value(substr($longText, $i, 1000));
}
$embed->addFields(...$fields);
429 Too Many Requests.FailureHandler:
use Symfony\Component\Notifier\Exception\TransportException;
$this->__invoke($failure) {
if ($failure->getException()
How can I help you explore Laravel packages today?