symfony/discord-notifier
Symfony Notifier bridge for Discord. Configure via DISCORD_DSN for webhooks or a bot token, then send ChatMessage notifications. Supports rich embeds and options (username, title, fields, thumbnails, footers) to build interactive Discord messages.
composer require symfony/discord-notifier
.env file:
DISCORD_DSN=discord://WEBHOOK_TOKEN@default?webhook_id=WEBHOOK_ID
For a bot token:
DISCORD_DSN=discord+bot://BOT_TOKEN@default
AppServiceProvider):
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Bridge\Discord\DiscordTransportFactory;
public function register()
{
$this->app->singleton(Notifier::class, function ($app) {
return new Notifier([
new DiscordTransportFactory(),
]);
});
}
use Symfony\Component\Notifier\Message\ChatMessage;
use Symfony\Component\Notifier\NotifierInterface;
$notifier = app(NotifierInterface::class);
$message = new ChatMessage('Hello from Laravel!');
$notifier->send($message);
Send a rich embed notification when a deployment completes:
$message = new ChatMessage('Deployment completed!');
$message->options((new DiscordOptions())
->addEmbed((new DiscordEmbed())
->title('Deployment Alert')
->description('New release deployed to production')
->color('green')
->addField((new DiscordFieldEmbedObject())
->name('Version')
->value('v1.2.3')
->inline(true)
)
->addField((new DiscordFieldEmbedObject())
->name('Status')
->value('✅ Success')
->inline(true)
)
->footer((new DiscordFooterEmbedObject())
->text('Deployed by CI/CD')
)
)
);
$notifier->send($message);
ChatMessage with your content.DiscordOptions to customize the message (e.g., embeds, username).Notifier (Symfony’s unified notification system).use Symfony\Component\Notifier\Bridge\Discord\Embeds\DiscordCodeBlockEmbedObject;
try {
// Risky operation
} catch (\Exception $e) {
$message = new ChatMessage('Error in `UserService::create()`');
$message->options((new DiscordOptions())
->username('Error Monitor')
->addEmbed((new DiscordEmbed())
->title('Critical Error')
->description($e->getMessage())
->color('red')
->addField((new DiscordFieldEmbedObject())
->name('File')
->value('app/Services/UserService.php')
)
->addField((new DiscordFieldEmbedObject())
->name('Line')
->value('42')
)
->addField((new DiscordFieldEmbedObject())
->name('Trace')
->value((new DiscordCodeBlockEmbedObject())
->content($e->getTraceAsString())
->language('php')
)
)
)
);
$notifier->send($message);
}
Leverage Laravel’s service container to resolve NotifierInterface:
use Symfony\Component\Notifier\NotifierInterface;
class DeploymentService {
public function __construct(private NotifierInterface $notifier) {}
public function deploy() {
// ... deployment logic ...
$this->notifier->send($this->buildDeploymentMessage());
}
}
For Laravel’s Notification facade, use spatie/laravel-notification-channels-discord as a wrapper:
use App\Notifications\DeploymentNotification;
use Illuminate\Notifications\Notification;
class DeploymentNotification extends Notification {
public function via($notifiable)
{
return ['discord'];
}
public function toDiscord($notifiable)
{
return (new ChatMessage('Deployment Alert'))
->options((new DiscordOptions())
->addEmbed($this->buildEmbed())
);
}
}
Reuse embed configurations with helper methods:
class DiscordEmbedHelper {
public static function errorEmbed(string $title, string $message, \Exception $e): DiscordEmbed
{
return (new DiscordEmbed())
->title($title)
->description($message)
->color('red')
->addField((new DiscordFieldEmbedObject())
->name('Exception')
->value(get_class($e))
)
->addField((new DiscordFieldEmbedObject())
->name('Trace')
->value((new DiscordCodeBlockEmbedObject())
->content($e->getTraceAsString())
->language('php')
)
);
}
}
Send multiple messages in a loop (e.g., for bulk alerts):
$users = User::where('last_login_at', '<', now()->subDays(30))->get();
foreach ($users as $user) {
$message = new ChatMessage("User {$user->name} inactive for 30+ days");
$message->options((new DiscordOptions())
->addEmbed((new DiscordEmbed())
->title('Inactive User Alert')
->description("User hasn’t logged in since {$user->last_login_at->format('Y-m-d')}")
->color('yellow')
->addField((new DiscordFieldEmbedObject())
->name('Email')
->value($user->email)
)
)
);
$notifier->send($message);
}
DSN Format:
discord://TOKEN@default?webhook_id=ID
TOKEN is the webhook URL token (not the full URL).webhook_id is optional if the DSN is discord://TOKEN@default (uses the token as ID).discord+bot://BOT_TOKEN@default
Environment Variables:
.env never in code or version control.config('services.discord') for structured access:
DISCORD_WEBHOOK_TOKEN=your_token_here
DISCORD_WEBHOOK_ID=your_webhook_id
config(['services.discord' => [
'token' => env('DISCORD_WEBHOOK_TOKEN'),
'id' => env('DISCORD_WEBHOOK_ID'),
]]);
Failed Messages:
TransportException on failures. Catch and log:
try {
$notifier->send($message);
} catch (\Symfony\Component\Notifier\Exception\TransportException $e) {
Log::error('Discord notification failed', ['error' => $e->getMessage()]);
}
Send Messages scope).Embed Validation:
DiscordOptions::validate() to catch issues early:
$options = (new DiscordOptions())->addEmbed($embed);
if (!$options->validate()) {
throw new \InvalidArgumentException('Invalid Discord embed');
}
Avoid Large Attachments:
Batch Processing:
$batch = [];
foreach ($logs as $log) {
$batch[] = new ChatMessage($log->message)
->options($this->buildLogEmbed($log));
}
foreach ($batch as $message) {
$notifier->send($message);
sleep(1); // Throttle to avoid rate limits
}
DiscordTransport to add features like message editing:
class CustomDiscordTransport extends DiscordTransport {
public function editMessage(string $messageId, ChatMessage $message): void {
How can I help you explore Laravel packages today?