Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Send Appointment Reminders with PHP and Laravel


(information)

Info

Ahoy! We now recommend you build your appointment reminders with Twilio's built in Message Scheduling functionality. Head on over to the Message Scheduling documentation to learn more about scheduling messages!

This Laravel 5(link takes you to an external page) web application shows how to create appointments for customers at a date in future, and send out reminders for those appointments in a background job(link takes you to an external page) that runs every few minutes.

In this tutorial, we'll point out the key bits of code that make this application work. Check out the project README on GitHub(link takes you to an external page) to see how to run the code yourself.

Check out how Yelp uses SMS to confirm restaurant reservations for diners.(link takes you to an external page)

Let's get started! Click the button below to begin.


Configure the application to use Twilio

configure-the-application-to-use-twilio page anchor

Before we can use the Twilio API to send reminder text messages, we need to configure our account credentials. These can be found on your Twilio Console. You'll also need an SMS-enabled phone number - you can find or purchase a new one to use here.

We configure these values using Dotenv(link takes you to an external page), the configuration library of choice for Laravel applications. More information on how to configure this application can be found in the project README(link takes you to an external page).

Configure the application

configure-the-application page anchor

.env.example


_17
APP_ENV=local
_17
APP_DEBUG=true
_17
APP_KEY=ufxhZiQcKxi1eHVmGq8MwfAcRgZHJ1Qq
_17
_17
DB_HOST=localhost
_17
DB_DATABASE=appointments
_17
DB_USERNAME=appointments
_17
DB_PASSWORD=appointments
_17
_17
# Twilio API credentials
_17
# Found at https://www.twilio.com/user/account/settings
_17
TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXX
_17
TWILIO_AUTH_TOKEN=your_token
_17
_17
# Twilio phone number
_17
# Purchase one at https://www.twilio.com/user/account/phone-numbers/incoming
_17
TWILIO_NUMBER=your_twilio_number

Next let's see how we create a new Appointment.


Create a new appointment

create-a-new-appointment page anchor

In order to send an appointment reminder, we first need to create an appointment! In the controller(link takes you to an external page), we take information submitted in a form(link takes you to an external page) (notably a customer's name and phone number, plus a time for the appointment in the future) and save it in an Appointment model.

Notice that we use the Carbon date library(link takes you to an external page) to make it easier for us to parse and do simple operations with the time.

app/Http/Controllers/AppointmentController.php


_100
<?php
_100
_100
namespace App\Http\Controllers;
_100
_100
use Illuminate\Http\Request;
_100
use Illuminate\Http\Response;
_100
use Carbon\Carbon;
_100
_100
use App\Http\Requests;
_100
use App\Http\Controllers\Controller;
_100
_100
class AppointmentController extends Controller
_100
{
_100
private $appointment;
_100
private $validInputConditions = array(
_100
'name' => 'required',
_100
'phoneNumber' => 'required|min:5',
_100
'when' => 'required',
_100
'timezoneOffset' => 'required',
_100
'delta' => 'required|numeric'
_100
);
_100
_100
/**
_100
* Display a listing of the resource.
_100
*
_100
* @return Response
_100
*/
_100
public function index()
_100
{
_100
$allAppointments = \App\Appointment::orderBy('id', 'ASC')->get();
_100
return response()->view('appointment.index', array('apts' => $allAppointments));
_100
}
_100
_100
/**
_100
* Show the form for creating a new resource.
_100
*
_100
* @return Response
_100
*/
_100
public function create()
_100
{
_100
$appointment = new \App\Appointment;
_100
return \View::make('appointment.create', array('appointment' => $appointment));
_100
}
_100
_100
/**
_100
* Store a newly created resource in storage.
_100
*
_100
* @return Response
_100
*/
_100
public function store(Request $request)
_100
{
_100
$newAppointment = $this->appointmentFromRequest($request);
_100
$newAppointment->save();
_100
return redirect()->route('appointment.index');
_100
}
_100
_100
/**
_100
* Delete a resource in storage.
_100
*
_100
* @return Response
_100
*/
_100
public function destroy($id) {
_100
\App\Appointment::find($id)->delete();
_100
return redirect()->route('appointment.index');
_100
}
_100
_100
public function edit($id) {
_100
$appointmentToEdit = \App\Appointment::find($id);
_100
return \View::make('appointment.edit', array('appointment' => $appointmentToEdit));
_100
}
_100
_100
public function update(Request $request, $id) {
_100
$updatedAppointment = $this->appointmentFromRequest($request);
_100
$existingAppointment = \App\Appointment::find($id);
_100
_100
$existingAppointment->name = $updatedAppointment->name;
_100
$existingAppointment->phoneNumber = $updatedAppointment->phoneNumber;
_100
$existingAppointment->timezoneOffset = $updatedAppointment->timezoneOffset;
_100
$existingAppointment->when = $updatedAppointment->when;
_100
$existingAppointment->notificationTime = $updatedAppointment->notificationTime;
_100
_100
$existingAppointment->save();
_100
return redirect()->route('appointment.index');
_100
}
_100
_100
private function appointmentFromRequest(Request $request) {
_100
$this->validate($request, $this->validInputConditions);
_100
$newAppointment = new \App\Appointment;
_100
_100
$newAppointment->name = $request->input('name');
_100
$newAppointment->phoneNumber = $request->input('phoneNumber');
_100
$newAppointment->timezoneOffset = $request->input('timezoneOffset');
_100
$newAppointment->when = $request->input('when');
_100
_100
$notificationTime = Carbon::parse($request->input('when'))->subMinutes($request->delta);
_100
$newAppointment->notificationTime = $notificationTime;
_100
_100
return $newAppointment;
_100
}
_100
}

Now that we have our Appointment created, let's see how to schedule a reminder for it.


Schedule a job to send reminders

schedule-a-job-to-send-reminders page anchor

Every ten minutes, we'd like our application to check the appointments database to see if any appointments are coming up that require reminders to be sent out. We configure both the job code we'd like to run and the interval on which to run it here.

Schedule a job to send reminders

schedule-a-job-to-send-reminders-1 page anchor

app/Console/Kernel.php


_41
<?php
_41
_41
namespace App\Console;
_41
_41
use Illuminate\Console\Scheduling\Schedule;
_41
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
_41
_41
class Kernel extends ConsoleKernel
_41
{
_41
/**
_41
* The Artisan commands provided by your application.
_41
*
_41
* @var array
_41
*/
_41
protected $commands = [
_41
'\App\Console\Commands\SendReminders'
_41
];
_41
_41
/**
_41
* Define the application's command schedule.
_41
*
_41
* @param \Illuminate\Console\Scheduling\Schedule $schedule
_41
* @return void
_41
*/
_41
protected function schedule(Schedule $schedule)
_41
{
_41
$schedule->command('reminders:send')->everyMinute();
_41
}
_41
_41
/**
_41
* Register the commands for the application.
_41
*
_41
* @return void
_41
*/
_41
protected function commands()
_41
{
_41
$this->load(__DIR__.'/Commands');
_41
_41
require base_path('routes/console.php');
_41
}
_41
}

With our job configured, we're now ready to write the actual console command code that will send out our reminders.


Create a console command to run the job

create-a-console-command-to-run-the-job page anchor

To actually execute our recurring job logic, we create an Artisan console command(link takes you to an external page) which queries the database for upcoming appointments and sends reminders as necessary. As an added bonus, defining our job logic in this way allows us to run the reminder job whenever we want from the command line.

Create a console command to run the job

create-a-console-command-to-run-the-job-1 page anchor

app/Console/Commands/SendReminders.php


_43
<?php
_43
_43
namespace App\Console\Commands;
_43
_43
use Illuminate\Console\Command;
_43
_43
class SendReminders extends Command
_43
{
_43
/**
_43
* The name and signature of the console command.
_43
*
_43
* @var string
_43
*/
_43
protected $signature = 'reminders:send';
_43
_43
/**
_43
* The console command description.
_43
*
_43
* @var string
_43
*/
_43
protected $description = 'Send reminders using Twilio';
_43
_43
/**
_43
* Create a new command instance.
_43
*
_43
* @return void
_43
*/
_43
public function __construct()
_43
{
_43
parent::__construct();
_43
}
_43
_43
/**
_43
* Execute the console command.
_43
*
_43
* @return void
_43
*/
_43
public function handle()
_43
{
_43
$appointmentReminder = new \App\AppointmentReminders\AppointmentReminder();
_43
$appointmentReminder->sendReminders();
_43
}
_43
}

Let's dig further into the ApplicationReminder class


Find appointments that need reminders

find-appointments-that-need-reminders page anchor

Our recurring job uses an instance of the AppointmentReminder class to query the database for appointments coming up in the next ten minutes and send out reminder messages.

In the constructor, we execute the database query using a custom scope(link takes you to an external page) on the Appointment model. This should give us a list of all appointments with a date and time that falls within the next ten minutes.

Find appointments that need reminders

find-appointments-that-need-reminders-1 page anchor

app/AppointmentReminders/AppointmentReminder.php


_78
<?php
_78
_78
namespace App\AppointmentReminders;
_78
_78
use Illuminate\Log;
_78
use Carbon\Carbon;
_78
use Twilio\Rest\Client;
_78
_78
class AppointmentReminder
_78
{
_78
/**
_78
* Construct a new AppointmentReminder
_78
*
_78
* @param Illuminate\Support\Collection $twilioClient The client to use to query the API
_78
*/
_78
function __construct()
_78
{
_78
$this->appointments = \App\Appointment::appointmentsDue()->get();
_78
_78
$twilioConfig =\Config::get('services.twilio');
_78
$accountSid = $twilioConfig['twilio_account_sid'];
_78
$authToken = $twilioConfig['twilio_auth_token'];
_78
$this->sendingNumber = $twilioConfig['twilio_number'];
_78
_78
$this->twilioClient = new Client($accountSid, $authToken);
_78
}
_78
_78
/**
_78
* Send reminders for each appointment
_78
*
_78
* @return void
_78
*/
_78
public function sendReminders()
_78
{
_78
$this->appointments->each(
_78
function ($appointment) {
_78
$this->_remindAbout($appointment);
_78
}
_78
);
_78
}
_78
_78
/**
_78
* Sends a message for an appointment
_78
*
_78
* @param Appointment $appointment The appointment to remind
_78
*
_78
* @return void
_78
*/
_78
private function _remindAbout($appointment)
_78
{
_78
$recipientName = $appointment->name;
_78
$time = Carbon::parse($appointment->when, 'UTC')
_78
->subMinutes($appointment->timezoneOffset)
_78
->format('g:i a');
_78
_78
$message = "Hello $recipientName, this is a reminder that you have an appointment at $time!";
_78
$this->_sendMessage($appointment->phoneNumber, $message);
_78
}
_78
_78
/**
_78
* Sends a single message using the app's global configuration
_78
*
_78
* @param string $number The number to message
_78
* @param string $content The content of the message
_78
*
_78
* @return void
_78
*/
_78
private function _sendMessage($number, $content)
_78
{
_78
$this->twilioClient->messages->create(
_78
$number,
_78
array(
_78
"from" => $this->sendingNumber,
_78
"body" => $content
_78
)
_78
);
_78
}
_78
}

Now let's setup the Twilio REST Client in order to send some SMS reminder messages.


Set up a Twilio API client

set-up-a-twilio-api-client page anchor

Also in the AppointmentReminder constructor, we create a Twilio REST Client to send out reminders via SMS. We initialize it with the Twilio account credentials we configured earlier.

app/AppointmentReminders/AppointmentReminder.php


_78
<?php
_78
_78
namespace App\AppointmentReminders;
_78
_78
use Illuminate\Log;
_78
use Carbon\Carbon;
_78
use Twilio\Rest\Client;
_78
_78
class AppointmentReminder
_78
{
_78
/**
_78
* Construct a new AppointmentReminder
_78
*
_78
* @param Illuminate\Support\Collection $twilioClient The client to use to query the API
_78
*/
_78
function __construct()
_78
{
_78
$this->appointments = \App\Appointment::appointmentsDue()->get();
_78
_78
$twilioConfig =\Config::get('services.twilio');
_78
$accountSid = $twilioConfig['twilio_account_sid'];
_78
$authToken = $twilioConfig['twilio_auth_token'];
_78
$this->sendingNumber = $twilioConfig['twilio_number'];
_78
_78
$this->twilioClient = new Client($accountSid, $authToken);
_78
}
_78
_78
/**
_78
* Send reminders for each appointment
_78
*
_78
* @return void
_78
*/
_78
public function sendReminders()
_78
{
_78
$this->appointments->each(
_78
function ($appointment) {
_78
$this->_remindAbout($appointment);
_78
}
_78
);
_78
}
_78
_78
/**
_78
* Sends a message for an appointment
_78
*
_78
* @param Appointment $appointment The appointment to remind
_78
*
_78
* @return void
_78
*/
_78
private function _remindAbout($appointment)
_78
{
_78
$recipientName = $appointment->name;
_78
$time = Carbon::parse($appointment->when, 'UTC')
_78
->subMinutes($appointment->timezoneOffset)
_78
->format('g:i a');
_78
_78
$message = "Hello $recipientName, this is a reminder that you have an appointment at $time!";
_78
$this->_sendMessage($appointment->phoneNumber, $message);
_78
}
_78
_78
/**
_78
* Sends a single message using the app's global configuration
_78
*
_78
* @param string $number The number to message
_78
* @param string $content The content of the message
_78
*
_78
* @return void
_78
*/
_78
private function _sendMessage($number, $content)
_78
{
_78
$this->twilioClient->messages->create(
_78
$number,
_78
array(
_78
"from" => $this->sendingNumber,
_78
"body" => $content
_78
)
_78
);
_78
}
_78
}

With the client and the reminders in hand. All that is left is to send an SMS for them.


Send reminder messages with the Twilio API

send-reminder-messages-with-the-twilio-api page anchor

These two private functions are called for every appointment coming up that requires a reminder to be sent. The first formats the text of the message to be sent out. The second actually uses the Twilio REST API client to send out a text message.

We provide a to parameter which is the customer's phone number, a from parameter which is a number in our account, and a body parameter which contains the text of the message.

Send reminder messages with the Twilio API

send-reminder-messages-with-the-twilio-api-1 page anchor

app/AppointmentReminders/AppointmentReminder.php


_78
<?php
_78
_78
namespace App\AppointmentReminders;
_78
_78
use Illuminate\Log;
_78
use Carbon\Carbon;
_78
use Twilio\Rest\Client;
_78
_78
class AppointmentReminder
_78
{
_78
/**
_78
* Construct a new AppointmentReminder
_78
*
_78
* @param Illuminate\Support\Collection $twilioClient The client to use to query the API
_78
*/
_78
function __construct()
_78
{
_78
$this->appointments = \App\Appointment::appointmentsDue()->get();
_78
_78
$twilioConfig =\Config::get('services.twilio');
_78
$accountSid = $twilioConfig['twilio_account_sid'];
_78
$authToken = $twilioConfig['twilio_auth_token'];
_78
$this->sendingNumber = $twilioConfig['twilio_number'];
_78
_78
$this->twilioClient = new Client($accountSid, $authToken);
_78
}
_78
_78
/**
_78
* Send reminders for each appointment
_78
*
_78
* @return void
_78
*/
_78
public function sendReminders()
_78
{
_78
$this->appointments->each(
_78
function ($appointment) {
_78
$this->_remindAbout($appointment);
_78
}
_78
);
_78
}
_78
_78
/**
_78
* Sends a message for an appointment
_78
*
_78
* @param Appointment $appointment The appointment to remind
_78
*
_78
* @return void
_78
*/
_78
private function _remindAbout($appointment)
_78
{
_78
$recipientName = $appointment->name;
_78
$time = Carbon::parse($appointment->when, 'UTC')
_78
->subMinutes($appointment->timezoneOffset)
_78
->format('g:i a');
_78
_78
$message = "Hello $recipientName, this is a reminder that you have an appointment at $time!";
_78
$this->_sendMessage($appointment->phoneNumber, $message);
_78
}
_78
_78
/**
_78
* Sends a single message using the app's global configuration
_78
*
_78
* @param string $number The number to message
_78
* @param string $content The content of the message
_78
*
_78
* @return void
_78
*/
_78
private function _sendMessage($number, $content)
_78
{
_78
$this->twilioClient->messages->create(
_78
$number,
_78
array(
_78
"from" => $this->sendingNumber,
_78
"body" => $content
_78
)
_78
);
_78
}
_78
}

That's it! Our Laravel application is all set to send out reminders for upcoming appointments.


We hope you found this sample application useful. If you're a PHP developer working with Twilio, you might enjoy these other tutorials:

Click to Call

Put a button on your web page that connects visitors to live support or sales people via telephone.

Two-Factor Authentication

Improve the security of Laravel's built-in login functionality by adding two-factor authentication via text message.

Did this help?

did-this-help page anchor

Thanks for checking out this tutorial! If you have any feedback to share with us, please reach out on Twitter(link takes you to an external page)... we'd love to hear your thoughts, and know what you're building!


Rate this page: