artox-lab/clarc-notification-bundle
Installation:
composer require artox-lab/clarc-notification-bundle
Enable the bundle in config/bundles.php:
ArtoxLab\Bundle\ClarcNotificationBundle\ArtoxLabClarcNotificationBundle::class => ['all' => true],
First Use Case:
Create a custom notification entity (e.g., App\Entities\Notification\WelcomeNotification) extending the bundle’s base structure. Implement a presenter (e.g., App\Interfaces\Notification\WelcomeNotificationPresenter) to format the notification content.
// ExampleNotification.php
namespace App\Entities\Notification;
use ArtoxLab\Bundle\ClarcNotificationBundle\Notification\Entities\Notification;
class WelcomeNotification extends Notification {
public function __construct(string $userName) {
$this->setData(['user_name' => $userName]);
}
}
Register the notification in your service container (e.g., via config/services.yaml):
services:
App\Interfaces\Notification\WelcomeNotificationPresenter:
tags: ['clarc_notification.presenter']
Send a Notification:
Inject the NotifierInterface into a service and dispatch:
use ArtoxLab\Bundle\ClarcNotificationBundle\Notification\Entities\Notifier\NotifierInterface;
use ArtoxLab\Bundle\ClarcNotificationBundle\Notification\Entities\Recipient\EmailRecipient;
class WelcomeService {
public function __construct(private NotifierInterface $notifier) {}
public function sendWelcomeEmail(string $email, string $userName) {
$notification = new WelcomeNotification($userName);
$recipient = new EmailRecipient($email);
$this->notifier->notify($notification, $recipient);
}
}
Notification Lifecycle:
Notification or implement NotificationInterface with your data.NotifierInterface and call notify() with the notification and recipient(s).Recipient Handling:
EmailRecipient, SmsRecipient) or create custom ones (e.g., SlackRecipient).$this->notifier->notify($notification, [$recipient1, $recipient2]);
Transport Integration:
TransportInterface for custom channels (e.g., Webhook, Push):
class WebhookTransport implements TransportInterface {
public function send(Notification $notification, RecipientInterface $recipient): void {
// Logic to send via HTTP
}
}
config/packages/clarc_notification.yaml:
clarc_notification:
transports:
webhook: App\Transport\WebhookTransport
Dependency Injection:
tags: ['clarc_notification.presenter', 'clarc_notification.transport']
Event-Driven Notifications:
Listen to domain events (e.g., UserRegisteredEvent) and dispatch notifications in event handlers:
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class UserRegisteredSubscriber implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [UserRegisteredEvent::class => 'onUserRegistered'];
}
public function onUserRegistered(UserRegisteredEvent $event) {
$this->notifier->notify(new WelcomeNotification($event->getUserName()), new EmailRecipient($event->getEmail()));
}
}
Dynamic Recipients: Fetch recipients from a database or API and loop through them:
foreach ($user->getSubscribedEmails() as $email) {
$this->notifier->notify($notification, new EmailRecipient($email));
}
Fallback Transports:
Configure fallback transports in clarc_notification.yaml to retry failed deliveries:
clarc_notification:
transports:
email:
class: App\Transport\EmailTransport
fallback: sms
Presenter Priority:
tags: ['clarc_notification.presenter', { priority: 10 }]
Transport Configuration:
clarc_notification.yaml; otherwise, notifications will fail silently.debug:container to verify service registration.Recipient Validation:
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException('Invalid email');
}
Circular Dependencies:
NotifierInterface into presenters/transports to prevent circular dependencies. Use method injection or pass dependencies explicitly.Symfony 6+ Compatibility:
AppKernel) may cause issues. Use config/bundles.php as shown in the README.Log Notifications:
Enable debug logging in config/packages/dev/clarc_notification.yaml:
clarc_notification:
debug: true
Logs will appear in var/log/dev.log.
Test Transports: Use a mock transport for testing:
class MockTransport implements TransportInterface {
public function send(Notification $notification, RecipientInterface $recipient): void {
// Log or assert notification data
}
}
Register it in config/packages/test/clarc_notification.yaml:
clarc_notification:
transports:
mock: App\Transport\MockTransport
Profiler Integration:
Install symfony/profiler-pack to inspect notification dispatches in the Symfony profiler.
Custom Notification Types:
Extend the base Notification class or implement NotificationInterface for domain-specific needs:
interface NotificationInterface {
public function getData(): array;
public function getType(): string;
}
Channel-Specific Logic: Use presenters to add channel-specific logic (e.g., SMS character limits, email templates):
class EmailPresenter implements PresenterInterface {
public function present(Notification $notification): string {
return $this->twig->render('emails/welcome.html.twig', $notification->getData());
}
}
Async Processing: Integrate with Symfony Messenger or a queue system (e.g., RabbitMQ) to process notifications asynchronously:
use Symfony\Component\Messenger\MessageBusInterface;
class AsyncNotifier {
public function __construct(private MessageBusInterface $bus) {}
public function notify(Notification $notification, RecipientInterface $recipient) {
$this->bus->dispatch(new NotificationMessage($notification, $recipient));
}
}
Rate Limiting:
Implement a decorator around NotifierInterface to enforce rate limits:
class RateLimitedNotifier implements NotifierInterface {
public function notify(Notification $notification, RecipientInterface $recipient): void {
if ($this->isRateLimited($recipient)) {
throw new \RuntimeException('Rate limit exceeded');
}
$this->decoratedNotifier->notify($notification, $recipient);
}
}
Localization: Use Symfony’s translation system in presenters to support multiple languages:
class EmailPresenter {
public function __construct(private TranslatorInterface $translator) {}
public function present(Notification $notification): string {
return $this->translator->trans(
'welcome.email.subject',
['%name%' => $notification->getData()['user_name']]
);
}
}
How can I help you explore Laravel packages today?