In this guide, we'll show you how to gather user input during a phone call through the phone's keypad (using DTMF tones) in your PHP application. By applying this technique, you can create interactive voice response (IVR) systems and other phone based interfaces for your users. The code snippets in this guide are written using PHP language features in PHP version 4.3 or higher, and make use of Twilio PHP SDK.
Let's get started!
This guide assumes you have already set up your web application to receive incoming phone calls. If you still need to complete this step, check out this guide. It should walk you through the process of buying a Twilio number, and configuring it to receive incoming calls.
The <Gather>
TwiML verb allows us to collect input from the user during a phone call. <Gather>
can have selected TwiML verbs nested within it, such as <Say>
and <Play>
. In this example, we will prompt the user to enter a number to connect to a certain department within our little IVR system.
1<?php2// Create a route that will handle Twilio webhook requests, sent as an3// HTTP POST to /voice in our application4require_once '/path/to/vendor/autoload.php';56use Twilio\TwiML\VoiceResponse;78// Use the Twilio PHP SDK to build an XML response9$response = new VoiceResponse();1011// Use the <Gather> verb to collect user input12$gather = $response->gather(array('numDigits' => 1));13// use the <Say> verb to request input from the user14$gather->say('For sales, press 1. For support, press 2.');1516// If the user doesn't enter input, loop17$response->redirect('/voice');1819// Render the response as XML in reply to the webhook request20header('Content-Type: text/xml');21echo $response;
If the user doesn't enter any input after a configurable timeout, Twilio will continue processing the TwiML in the document to determine what should happen next in the call, or it will hang up. In the above example, we use the <Redirect>
verb to have Twilio request the same URL again to prompt for input.
Now, if you were to run the example above and enter input, you would notice that you'd hear the same prompt over and over again regardless of what button you pressed. By default, if the user does enter input in the <Gather>
, Twilio will send another HTTP request to the current webhook URL with a POST
parameter containing the Digits entered by the user. In the sample above, we weren't handling this input at all. Let's update that logic to also process user input (if it is present).
1<?php2// Create a route that will handle Twilio webhook requests, sent as an3// HTTP POST to /voice in our application4require_once '/path/to/vendor/autoload.php';56use Twilio\TwiML\VoiceResponse;78// Use the Twilio PHP SDK to build an XML response9$response = new VoiceResponse();1011// If the user entered digits, process their request12if (array_key_exists('Digits', $_POST)) {13switch ($_POST['Digits']) {14case 1:15$response->say('You selected sales. Good for you!');16break;17case 2:18$response->say('You need support. We will help!');19break;20default:21$response->say('Sorry, I don\'t understand that choice.');22}23} else {24// If no input was sent, use the <Gather> verb to collect user input25$gather = $response->gather(array('numDigits' => 1));26// use the <Say> verb to request input from the user27$gather->say('For sales, press 1. For support, press 2.');2829// If the user doesn't enter input, loop30$response->redirect('/voice');31}3233// Render the response as XML in reply to the webhook request34header('Content-Type: text/xml');35echo $response;
1<?php2// Create a route that will handle Twilio webhook requests, sent as an3// HTTP POST to /voice in our application4require_once '/path/to/vendor/autoload.php';56use Twilio\TwiML\VoiceResponse;78// Use the Twilio PHP SDK to build an XML response9$response = new VoiceResponse();1011// If the user entered digits, process their request12if (array_key_exists('Digits', $_POST)) {13switch ($_POST['Digits']) {14case 1:15$response->say('You selected sales. Good for you!');16break;17case 2:18$response->say('You need support. We will help!');19break;20default:21$response->say('Sorry, I don\'t understand that choice.');22}23} else {24// If no input was sent, use the <Gather> verb to collect user input25$gather = $response->gather(array('numDigits' => 1));26// use the <Say> verb to request input from the user27$gather->say('For sales, press 1. For support, press 2.');2829// If the user doesn't enter input, loop30$response->redirect('/voice');31}3233// Render the response as XML in reply to the webhook request34header('Content-Type: text/xml');35echo $response;
Handling user input and prompts in the same webhook URL is fine, but you may want to have an entirely different endpoint in your application handle the processing of user input. This is possible using the "action" attribute of the <Gather>
verb. Let's update our example to add a second endpoint that will be responsible for handling user input.
1<?php2// Create a route that will handle Twilio webhook requests, sent as an3// HTTP POST to /voice in our application4require_once '/path/to/vendor/autoload.php';56use Twilio\TwiML\VoiceResponse;78// Use the Twilio PHP SDK to build an XML response9$response = new VoiceResponse();1011// Use the <Gather> verb to collect user input12$gather = $response->gather(array('numDigits' => 1, 'action' => '/gather'));13// use the <Say> verb to request input from the user14$gather->say('For sales, press 1. For support, press 2.');1516// If the user doesn't enter input, loop17$response->redirect('/voice');1819// Render the response as XML in reply to the webhook request20header('Content-Type: text/xml');21echo $response;
The action attribute takes a relative URL which would point to another route your server is capable of handling.
1<?php2// Create a route that will handle Twilio Gather verb action requests,3// sent as an HTTP POST to /gather in our application4require_once '/path/to/vendor/autoload.php';56use Twilio\TwiML\VoiceResponse;78// Use the Twilio PHP SDK to build an XML response9$response = new VoiceResponse();1011// If the user entered digits, process their request12if (array_key_exists('Digits', $_POST)) {13switch ($_POST['Digits']) {14case 1:15$response->say('You selected sales. Good for you!');16break;17case 2:18$response->say('You need support. We will help!');19break;20default:21$response->say('Sorry, I don\'t understand that choice.');22$response->redirect('/voice');23}24} else {25// If no input was sent, redirect to the /voice route26$response->redirect('/voice');27}2829// Render the response as XML in reply to the webhook request30header('Content-Type: text/xml');31echo $response;
Now, instead of conditional logic in a single route, we use actions and redirects to handle our call logic with separate code paths.
If you're building call center type applications in PHP, you might enjoy stepping through full sample applications written in PHP.