symfony/message-bird-notifier
Symfony Notifier bridge for MessageBird SMS. Configure via MESSAGEBIRD_DSN with your token and sender, then send SmsMessage instances. Supports advanced per-message settings through MessageBirdOptions (scheduling, encoding, callbacks, URL shortening, more).
Install the package via Composer:
composer require symfony/message-bird-notifier
Configure the DSN in your .env:
MESSAGEBIRD_DSN=messagebird://YOUR_MESSAGEBIRD_TOKEN@default?from=YOUR_SENDER_ID
YOUR_MESSAGEBIRD_TOKEN with your MessageBird API token.YOUR_SENDER_ID with your sender ID (e.g., phone number or alphanumeric sender ID).Register the transport in your Laravel/Symfony app:
// config/services.php (Laravel)
'notifier.transports' => [
'messagebird' => [
'dsn' => env('MESSAGEBIRD_DSN'),
],
],
Or in Symfony:
# config/packages/notifier.yaml
notifier:
transports:
messagebird:
dsn: '%env(MESSAGEBIRD_DSN)%'
Send your first SMS:
use Symfony\Component\Notifier\NotifierInterface;
use Symfony\Component\Notifier\Message\SmsMessage;
$notifier = app(NotifierInterface::class);
$notifier->send(new SmsMessage('+1234567890', 'Hello from Laravel!'));
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\Bridge\MessageBird\MessageBirdOptions;
$sms = new SmsMessage('+1234567890', 'Your password reset code: 123456');
$sms->options(
(new MessageBirdOptions())
->reference('password_reset_' . $user->id)
->validity(3600) // 1 hour validity
);
$notifier->send($sms);
Leverage Laravel’s queue system for async SMS delivery:
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Symfony\Component\Notifier\Message\SmsMessage;
class SendSmsJob implements ShouldQueue
{
use Dispatchable, Queueable;
public function __construct(
public string $phoneNumber,
public string $message,
public ?array $options = null
) {}
public function handle(NotifierInterface $notifier): void
{
$sms = new SmsMessage($this->phoneNumber, $this->message);
if ($this->options) {
$sms->options($this->options);
}
$notifier->send($sms);
}
}
Switch sender IDs based on region or use case:
$senderId = $user->region === 'eu' ? 'EU_SENDER_ID' : 'US_SENDER_ID';
$dsn = "messagebird://{$token}@default?from={$senderId}";
$notifier->send(new SmsMessage($phone, 'Hello'), ['dsn' => $dsn]);
Use Laravel events to trigger SMS:
// In an event listener
public function handle(UserRegistered $event)
{
$notifier->send(
new SmsMessage(
$event->user->phone,
"Welcome! Your account is ready."
)
);
}
$sms->options(
(new MessageBirdOptions())
->scheduledDatetime('2024-12-25T10:00:00') // Christmas reminder
);
$sms->options(
(new MessageBirdOptions())
->type('whatsapp')
);
$sms->options(
(new MessageBirdOptions())
->shortenUrls(true)
);
Use Mockery or VCR to avoid hitting MessageBird’s API:
// Example with Mockery
$mockTransport = Mockery::mock(MessageBirdTransport::class);
$mockTransport->shouldReceive('send')
->once()
->andReturn(new SentMessage());
$notifier = new Notifier([$mockTransport]);
$notifier->send(new SmsMessage('+1234567890', 'Test'));
$users = User::whereNotNull('phone')->get();
$users->each(function ($user) use ($notifier) {
$notifier->send(
new SmsMessage($user->phone, "Hello, {$user->name}!")
);
});
DSN Format Sensitivity:
from or malformed token) will throw InvalidArgumentException.MessageBirdTransport::getDsnParts().Phone Number Formatting:
+14155552671).Str::of($phone)->start('+') or a library like libphonenumber.Rate Limits:
retryAfter:
public function handle(): void
{
$this->retryAfter(5); // Retry after 5 seconds
}
Async Delivery Guarantees:
failed event to log failures:
SendSmsJob::failed(function (FailedJob $event) {
Log::error('SMS failed', ['job' => $event->job, 'exception' => $event->exception]);
});
Message Length Limits:
MessageBirdOptions::type('unicode') for non-ASCII text.Enable Verbose Logging:
$notifier->send($sms, ['debug' => true]);
Or configure Monolog in Symfony:
monolog:
handlers:
main:
level: debug
channels: ['!event']
Check MessageBird Webhooks:
Route::post('/messagebird/webhook', [MessageBirdWebhookHandler::class]);
Validate DSN:
$dsn = 'messagebird://token@default?from=sender';
$parts = MessageBirdTransport::getDsnParts($dsn);
if (empty($parts['token'])) {
throw new \RuntimeException('Invalid DSN');
}
Custom Transport:
Extend MessageBirdTransport to add logic (e.g., logging, analytics):
class CustomMessageBirdTransport extends MessageBirdTransport
{
protected function doSend(SmsMessage $message): void
{
// Add custom logic (e.g., track in database)
parent::doSend($message);
}
}
Event Listeners:
Listen to NotificationSent events:
public function handle(NotificationSent $event)
{
if ($event->message instanceof SmsMessage) {
// Log or analyze SMS
}
}
Dynamic Options:
Create a service to generate MessageBirdOptions dynamically:
class SmsOptionsGenerator
{
public function generateForReset(string $userId): MessageBirdOptions
{
return (new MessageBirdOptions())
->reference("reset_{$userId}")
->validity(3600);
}
}
Batch Processing:
Use Laravel’s chunk() for large datasets:
User::whereNotNull('phone')->chunk(100, function ($users) {
$users->each(fn ($user) => $notifier->send(...));
});
Caching Sender IDs: Cache sender IDs by region to avoid repeated DSN reconstruction:
Cache::remember("sender_id_{$region}", now()->addHours(1), fn () => $senderId);
Queue Priorities: Use Laravel’s queue priorities for urgent SMS:
How can I help you explore Laravel packages today?