Installation:
composer require laravel-notification-channels/twilio
Publish the config file (optional):
php artisan vendor:publish --provider="LaravelNotificationChannels\Twilio\TwilioServiceProvider"
Configure .env:
TWILIO_SID=your_account_sid
TWILIO_TOKEN=your_auth_token
TWILIO_FROM=+1234567890 # Optional: Default sender number
First Use Case: Send a basic SMS notification via a notification class:
use LaravelNotificationChannels\Twilio\TwilioChannel;
use LaravelNotificationChannels\Twilio\TwilioMessage;
class SendSmsNotification extends Notification
{
public function via($notifiable)
{
return [TwilioChannel::class];
}
public function toTwilio($notifiable)
{
return (new TwilioMessage())
->content('Hello from Laravel!');
}
}
Trigger it in a controller:
$user->notify(new SendSmsNotification());
Dynamic Recipients:
Use toTwilio() to dynamically set content or recipients:
public function toTwilio($notifiable)
{
return (new TwilioMessage())
->content("Your order #{$notifiable->order_id} is confirmed.")
->to($notifiable->phone); // Override default recipient
}
Media Attachments: Attach files (e.g., PDFs) to SMS:
public function toTwilio($notifiable)
{
return (new TwilioMessage())
->content('Your receipt is attached.')
->attach('path/to/receipt.pdf');
}
Channel-Specific Logic:
Use via() to conditionally send via Twilio:
public function via($notifiable)
{
return $notifiable->prefers_sms ? [TwilioChannel::class] : [];
}
Batch Sending: Queue notifications for efficiency:
$user->notify((new SendSmsNotification())->delay(now()->addMinutes(5)));
ResetPassword notification.public function via($notifiable)
{
return [MailChannel::class, TwilioChannel::class];
}
Rate Limits: Twilio enforces rate limits. Monitor usage via the Twilio Debugger. Fix: Implement exponential backoff in retries or use Twilio’s SMS Sync.
Phone Number Formatting:
Invalid numbers (e.g., +123) will fail silently. Validate with:
use Twilio\LibPhp\TwiML\Validator;
if (!Validator::isValidPhoneNumber($phone)) {
throw new \InvalidArgumentException('Invalid phone number');
}
Environment Variables:
Avoid hardcoding TWILIO_SID/TWILIO_TOKEN in code. Use .env or Laravel’s config().
Media Attachments: Large files (>10MB) may fail. Use Twilio’s Media API for larger files.
config/twilio.php:
'debug' => env('TWILIO_DEBUG', false),
Mockery to test locally:
$this->partialMock(TwilioClient::class, function ($mock) {
$mock->shouldReceive('messages')->andReturnSelf();
$mock->shouldReceive('create')->andReturn(new Twilio\Rest\Api\V2010\Account\MessageContext());
});
Default from Number:
If omitted, Twilio uses a random number from your account. Specify a dedicated number in .env:
TWILIO_FROM=+1234567890
Message Length:
SMS is limited to 1600 characters (360 chars per segment). Long messages auto-segment but cost more.
Tip: Use TwilioMessage::content() with plain text for best results.
Timeouts: Twilio’s API timeout is 30 seconds. For long-running tasks, use queues:
$user->notify(new SendSmsNotification())->onQueue('sms');
Custom Twilio Client:
Bind a custom TwilioClient instance in a service provider:
$this->app->singleton(TwilioClient::class, function () {
return new TwilioClient(
config('services.twilio.sid'),
config('services.twilio.token'),
['httpClient' => new GuzzleHttp\Client(['timeout' => 60])]
);
});
Event Listeners:
Listen for TwilioMessageSent events to log or process responses:
use LaravelNotificationChannels\Twilio\Events\TwilioMessageSent;
public function handle(TwilioMessageSent $event)
{
Log::info('SMS sent to ' . $event->message->to, ['sid' => $event->message->sid]);
}
Channel Extensions:
Extend TwilioChannel to add custom logic:
class CustomTwilioChannel extends TwilioChannel
{
public function send($notifiable, $message)
{
// Pre-process message (e.g., add tracking ID)
$message->content = "[ID: {$notifiable->id}] " . $message->content;
parent::send($notifiable, $message);
}
}
How can I help you explore Laravel packages today?