A channel-agnostic notification dispatcher for PHP. Build a Message, hand it
to a Notifier, and it fans out to every configured channel (email, Signal,
and any other you implement). A failing channel is isolated — subsequent
channels still run.
composer require g-giani/notifierRequires PHP 8.2+.
use GGiani\Notifier\{Notifier, Message, Severity};
use GGiani\Notifier\Channel\{EmailChannel, SignalChannel};
use Symfony\Component\Mailer\Mailer;
use Symfony\Component\Mailer\Transport;
use GuzzleHttp\Client;
$email = new EmailChannel(
mailer: new Mailer(Transport::fromDsn('smtp://user:pass@smtp.example.com:587')),
from: 'alerts@example.com',
to: ['ops@example.com'],
subjectPrefix: '[Monitor]',
);
$signal = new SignalChannel(
http: new Client(['base_uri' => 'http://localhost:8080/']),
sender: '+4915112345678',
recipients: ['+4915187654321'],
);
$notifier = new Notifier($email, $signal);
$failures = $notifier->notify(new Message(
title: 'Provider sync failed',
body: 'Provider.com returned no records for 3 consecutive runs.',
severity: Severity::Critical,
context: ['provider_id' => 117, 'process_id' => '5dhxl36s'],
));
// $failures is a list<ChannelException> — empty when everything went through.| Channel | Dependency | Notes |
|---|---|---|
EmailChannel |
symfony/mailer |
Accepts any Symfony DSN (SMTP, SES, Mailgun, …) |
SignalChannel |
HTTP | Targets signal-cli-rest-api |
NtfyChannel |
HTTP | Targets an ntfy server (self-hosted or ntfy.sh) |
SlackChannel |
HTTP | Slack Incoming Webhook |
DiscordChannel |
HTTP | Discord Webhook (rich embeds) |
MattermostChannel |
HTTP | Mattermost Incoming Webhook |
TelegramChannel |
HTTP | Telegram Bot API (sendMessage) |
GotifyChannel |
HTTP | Self-hosted Gotify |
GenericWebhookChannel |
HTTP | POST JSON payload to any URL |
NullChannel |
— | For tests / dry-run |
Implement GGiani\Notifier\Channel\ChannelInterface to add your own
(Telegram, Slack, WhatsApp, webhook, …). Throw ChannelException on failure
to let the Notifier continue with the remaining channels.
Notifier::notify() never throws — it returns the list of ChannelExceptions
from channels that failed, so the caller can decide what to do (log, retry,
escalate). If you want a logger wired in, call ->withLogger($psrLogger) —
failures are then also logged at error level.
MIT