Send an SMS in Laravel Using Vonage
Introduction
In your Laravel applications, there may be times that you want to send SMS messages to your users. You might want to do this to send notifications to your users, or maybe as a form of 2FA (two factor authentication).
To send the messages, you'll typically need to interact with a third-party service's API (such as Vonage or Twilio) that can handle the sending (and sometimes receiving) of your messages. In this guide, we're going to take a look at how to use Vonage (who were previously named Nexmo) to send an SMS message to your users from your Laravel app.
Vonage offers several different APIs that you can use, including:
- SMS API - for sending and receiving SMS
- Voice API - for making phone calls
- Video API - for making video calls
- Verify API - for adding 2FA functionality and verifying a user's phone number or identity
In this particular guide, we'll be using the SMS API.
Sending SMS Using Vonage
Create a Vonage Account
Before we touch any code in our projects, you'll first need to create a Vonage account. It's super simple and quick to do! After that, you'll be able to grab your API keys.
When you first sign up, you'll likely be given some free credit (I was given €2 EUR) and have some small restrictions placed on your account, such as:
- All of the SMS messages that you send will have a watermark at the end of the message (which says "[FREE SMS DEMO, TEST MESSAGE]")
- You'll only be able to send the message to your own phone number
But, this isn't an issue because it can give you a chance to experiment with the API and check whether its right for your project. Once you're ready to use Vonage and lift the restrictions, you can upgrade to a paid account.
Installation
Now that we've created our Vonage account and got our API keys, we can install Laravel's first-party notification channel for Vonage (laravel/vonage-notification-channel
) using the following command:
composer require laravel/vonage-notification-channel
We can then head over to our .env
file and add our API keys that we got after creating our Vonage account:
VONAGE_KEY=your-vonage-key-here
VONAGE_SECRET=your-vonage-secret-here
VONAGE_SMS_FROM=1234567890
As you can see, we've also added a VONAGE_SMS_FROM
field too. This will be the number (or name) that the message will appear as being sent by. If you've bought a phone number from Vonage, you may want to put that number here; or you might want to use your brand/company name here instead. Further down, we'll discuss how you can override this value on a notification-by-notification basis when sending the SMS messages.
Configuring Our Models
Now that we have the notification channel set up, we need to configure our model. In this example, we're going to imagine that we want to send the SMS to our User
models and that they have their phone number stored in a phone_number
field.
Whenever we send an SMS notification in Laravel, we need to let Laravel know where to grab the recipient's phone number from. At the moment, it has no idea which phone number to use. So, we create a new routeNotificationForVonage
method on our User
model that returns the phone_number
field. For example, we could update our model to look like so:
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
// ...
public function routeNotificationForVonage($notification)
{
return $this->phone_number;
}
}
You'll also need to make sure that your model is using the Illuminate\Notifications\Notifiable
trait so that we can use the notify
method to send the notification later.
We've now specified that whenever we are sending a notification using the Vonage channel that we should send the SMS to the user's phone number that's stored in the phone_number
field.
Create the Notification
Now that we've configured our model, we can create a new notification class. For the purpose of this tutorial, we're going to imagine that we want to send an SMS notification to a user once they've registered for our application.
So, we'll start by creating the notification using the following command:
php artisan make:notification SuccessfulRegistration
Running the command should have created a new notification class in the app/Notifications
directory. We can then update the class so that it can be used for sending SMS messages:
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\VonageMessage;
use Illuminate\Notifications\Notification;
class SuccessfulRegistration extends Notification implements ShouldQueue
{
use Queueable;
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['vonage'];
}
/**
* Get the Vonage / SMS representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\VonageMessage
*/
public function toVonage($notifiable)
{
return (new VonageMessage())
->content('You have now registered for My Amazing App!');
}
}
As you can see, we've specified that the via
method returns ['vonage']
. We've also added a new toVonage
method that returns an instance of Illuminate\Notifications\Messages\VonageMessage
with our SMS message content.
You might have also noticed that I've also made sure that the class implements the ShouldQueue
interface. This means that if we send the SMS as part of a request, we won't need to wait for the SMS to be sent before we return the response to the user. Instead, the SMS will be dispatched and run by one of our project's queue workers in the background. I've talked about using this approach in the past and how it can speed up your Laravel projects in my 6 Quick & Easy Ways to Speed Up Your Laravel Website article if you're interested in reading more.
Sending the Notification
Now that we've prepared our notification, we can now send it. To do this, we can use the notify
method (that we get access to via the Notifiable
trait on the User
model) like so:
$user->notify(new SuccessfulRegistration());
Your user should now receive an SMS message saying "You have now registered for My Amazing App!".
Taking it Further
Now that we've seen how we can send a simple SMS message to a user, let's take a look at how we could take this a little bit further.
Passing Extra Information to the SMS
You might sometimes want to send extra information in the SMS to the user. As a basic example, let's imagine that we also want to display the browser that the user was using when they signed up. We could grab this information like shown in my Getting the User's Device, Browser & OS in Laravel. We'll then want to update our notification class to accept this information like so:
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\VonageMessage;
use Illuminate\Notifications\Notification;
class SuccessfulRegistration extends Notification implements ShouldQueue
{
use Queueable;
public function __construct(private string $browser)
{
//
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['vonage'];
}
/**
* Get the Vonage / SMS representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\VonageMessage
*/
public function toVonage($notifiable)
{
return (new VonageMessage())
->content('You have now registered for My Amazing App using '.$this->browser.'!');
}
}
Notice how we've added a constructor to the notification that accepts a $browser
parameter as a string.
We can now update our method call to pass this extra information in like so:
use Jenssegers\Agent\Facades\Agent;
$user->notify(new SuccessfulRegistration(Agent::browser()));
In this particular example, we are using the (jenssegers/agent) package to determine the user's browser. For the purpose of the article, we'll make the assumption that the Agent::browser
call returns "Firefox". So, our user should now have received an SMS saying: "You have now registered for My Amazing App using Firefox!"
On-demand Vonage SMS Notifications
There may be times that you want to send notifications to someone that doesn't exist in your database. For example, you might want to send an SMS to yourself everytime someone completes a sign up or purchases something from your website. To do this, we can make use of Laravel's "on-demand notifications".
As an example, let's take a look at how we could send a notification to ourselves. First of all, we'll want to create a new config variable. It's important to remember that you should never hard code credentials, emails, or phone numbers in code as it can pose a security risk if your code is ever compromised (whether that be by a disgruntled ex-employee, or a malicious hacker). This is actually a topic that I'll be covering in more detail in my upcoming ebook Battle Ready Laravel if you're interested in reading more about it.
You should choose the best place to put this field depending on what you're using it for, but in this particular example, I'm going to call it admin_sms_number
and I'm just going to place it at the bottom of my config/app.php
config file:
return [
// ...
'admin_sms_number' => env('ADMIN_SMS_NUMBER'),
// ...
];
We'll then want to add the ADMIN_SMS_NUMBER
to our .env
file:
ADMIN_SMS_NUMBER=1234567890
We can now write our code to send the notification. We're going to imagine that we've followed the guide above to create a new notification that we've called NewUserRegistered
and already has the content set up. We'll also assume that the constructor accepts a parameter with the user's email address. So, we can send the notification like so:
use Illuminate\Support\Facades\Notification;
Notification::route('vonage', config('app.admin_sms_number'))
->notify(new NewUserRegistered($user->email));
The really nice thing about using on-demand notifications like these are that you can send notifications on multiple channels at once. For example, if we added the functionality to our NewUserRegistered
class to send emails, we could extend our above code to also send an SMS and email at the same time:
use Illuminate\Support\Facades\Notification;
Notification::route('vonage', config('app.admin_sms_number'))
->route('mail', config('app.admin_email_address'))
->notify(new NewUserRegistered($user->email));
Using a Different "From" Number or Name
By default, all of the messages will be sent using your VONAGE_SMS_FIELD
field that you defined in your .env
file. However, there may be times when you're creating your SMS messages that you'll want to change the "from" number or name. For example, let's say that you want to override the "from" number when sending out a specific notification. To do this, you can override the "from" number or name inside the notification class using the from
method.
Let's say that we want to set our SuccessfulRegistration
notification from above to be sent from "My Awesome App". We could update the toVonage
method in the class like so:
public function toVonage($notifiable)
{
return (new VonageMessage())
->from('My Awesome App')
->content('You have now registered for My Amazing App');
}
Now, when the user receives the SMS, it should show up as being received from "My Awesome App".
Conclusion
Hopefully, this post should have shown you how you can use Vonage to send SMS messages to your users in your Laravel applications. It should have also given you a quick insight into how you can send on-demand SMS notifications, pass extra information to the SMS, and also change the "from" number on a notification-by-notification basis.
If you enjoyed reading this post, I'd love to hear about it. Likewise, if you have any feedback to improve the future ones, I'd also love to hear that too.
If you're interested in getting updated each time I publish a new post, feel free to sign up for my newsletter.
Keep on building awesome stuff! 🚀
driesvints, felixramowda liked this article
Other articles you might like
How to add WebAuthn Passkeys To Backpack Admin Panel
Want to make your Laravel Backpack admin panel more secure with a unique login experience for your a...
Quickest way to setup PHP Environment (Laravel Herd + MySql)
Setting up a local development environment can be a time taking hassle—whether it's using Docker or...
Access Route Model-Bound Models with "#[RouteParameter]"
Introduction I've recently been using the new #[RouteParameter] attribute in Laravel, and I've been...
The Laravel portal for problem solving, knowledge sharing and community building.
The community