Phone Calls and SMS
from PHP
PHP World 2016
David Stockton
November 16, 2016
Standard Interactions
Input
Web Pages / Forms
APIs
CLI
Output
HTML
Graphics
Documents
Reports
JSON
Console Output
Files
How else can we receive
input and produce
output?
Input:
Phone Call
Input:
SMS Message
Output:
Text Message
Output:
MMS Message
Output:
Phone Call
APIs for Phone
Interaction
Twilio SDK
composer require twilio/sdk
Let's Send an SMS
new TwilioRestClient($config['sid'], $config['token']);
Make a client
Let's Send an SMS
$client->messages->create(

$toNumber,

array(

'from' => '+1<purchased#>',

'body' => $fortune

)

);
All Together
$toNumber = $argv[1] ?? '<default #>';



$toNumber = PhpWorld
Utility::normalizeNumber($toNumber);



$fortune = $argv[2] ?? `fortune`;



$client->messages->create(

$toNumber,

array(

'from' => '+<purchased #>',

'body' => $fortune

)

);
How to Use?
$ php bin/fortune.php
$ php bin/fortune.php <destination #>
$ php bin/fortune.php <destination #> "Text
message from the command line"
php bin/fortune.php
php bin/fortune.php 7206757471
php bin/fortune.php 7206757471 "Your account has been created or something."
What can we do?
• Notifications
• Two-Factor Authentication (2FA)
• Responses to Queries
Make a Phone Call
• API Call to Twitter
• Twitter contacts URL for instructions
TwiML
• Twilio's Markup Language for controlling phone
calls
• XML
TwiML Commands
• Say - Read text to the caller
• Play - Play an audio file for the caller
• Dial - Add another party to the call
• Record - Record the caller's voice
• Gather - Collect digits the caller types on their keypad
• Sms - Send an SMS message during a phone call
More TwiML
• Hangup - Hang up the call
• Queue - Add the caller to a queue of callers.
• Redirect - Redirect call flow to a different TwiML
document.
• Pause - Wait before executing more instructions
• Reject - Decline an incoming call without being billed.
• Message - Send an MMS or SMS message reply
How Outgoing Calls Work
Your App TwilioAPI Call
TwiML
CalleeTwilio Plays Twiml
TwiML
<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say voice="woman">Your call is very

important to us, but not so

important we'll answer it with

a human. Please leave a message.

</Say>

<Record maxLength="20" playBeep="true"/>

</Response>
XML
<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say voice="woman">Your call is very

important to us, but not so

important we'll answer it with

a human. Please leave a message.

</Say>

<Record maxLength="20" playBeep="true"/>

</Response>
Root Element
<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say voice="woman">Your call is very

important to us, but not so

important we'll answer it with

a human. Please leave a message.

</Say>

<Record maxLength="20" playBeep="true"/>

</Response>
Commands - Say
<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say voice="woman">Your call is very

important to us, but not so

important we'll answer it with

a human. Please leave a message.

</Say>

<Record maxLength="20" playBeep="true"/>

</Response>
<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say voice="woman">Your call is very

important to us, but not so

important we'll answer it with

a human. Please leave a message.

</Say>

<Record maxLength="20" playBeep="true"/>

</Response>
Commands - Record
Configure Twilio
Let's Make a Call
<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say voice="man">

Due to inclement weather, school

will be closed tomorrow. Please

stay home and stay safe.

</Say>

</Response>
The Full File
<?php header('Content-Type: text/xml'); ?>

<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say voice="man" loop="2">

Due to inclement weather, school

will be closed tomorrow. Please

stay home and stay safe.

</Say>

</Response>
Tell Twilio Who To Call
<?php

require_once __DIR__ . '/../vendor/autoload.php';

/** @var TwilioRestClient $client */

$client = require_once __DIR__ . '/../src/PhpWorld/client.php';



$to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');

$from = '+<purchased #>';



$options = [

'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/
school_outage.php',

];



$client->calls->create($to, $from, $options);
Tell Twilio Who To Call
<?php

require_once __DIR__ . '/../vendor/autoload.php';

/** @var TwilioRestClient $client */

$client = require_once __DIR__ . '/../src/PhpWorld/client.php';



$to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');

$from = '+<purchased #>';



$options = [

'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/
school_outage.php',

];



$client->calls->create($to, $from, $options);
Tell Twilio Who To Call
<?php

require_once __DIR__ . '/../vendor/autoload.php';

/** @var TwilioRestClient $client */

$client = require_once __DIR__ . '/../src/PhpWorld/client.php';



$to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');

$from = '+<purchased #>';



$options = [

'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/
school_outage.php',

];



$client->calls->create($to, $from, $options);
Tell Twilio Who To Call
<?php

require_once __DIR__ . '/../vendor/autoload.php';

/** @var TwilioRestClient $client */

$client = require_once __DIR__ . '/../src/PhpWorld/client.php';



$to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');

$from = '+<purchased #>';



$options = [

'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/
school_outage.php',

];



$client->calls->create($to, $from, $options);
Tell Twilio Who To Call
<?php

require_once __DIR__ . '/../vendor/autoload.php';

/** @var TwilioRestClient $client */

$client = require_once __DIR__ . '/../src/PhpWorld/client.php';



$to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');

$from = '+<purchased #>';



$options = [

'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/
school_outage.php',

];



$client->calls->create($to, $from, $options);
Tell Twilio Who To Call
<?php

require_once __DIR__ . '/../vendor/autoload.php';

/** @var TwilioRestClient $client */

$client = require_once __DIR__ . '/../src/PhpWorld/client.php';



$to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');

$from = '+<purchased #>';



$options = [

'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/
school_outage.php',

];



$client->calls->create($to, $from, $options);
Phone and SMS
Conversations
• Twilio is like a well-behaved HTTP client
• It uses sessions
• We can use session to remember things about the
caller or the conversation
Phone IVR
• Give callers a menu
• Look up information
• Connect to people
• Solve problems
• Give answers
First TwiML
<?php header('Content-Type: text/xml'); ?>

<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say>

Thanks for calling my demo IVR. Please

listen closely as this is the first time

you've heard this menu.

</Say>

<Gather numDigits="1" action="/twiml/process_ivr_menu.php">

<Say>

Press 1 to hear a random sound.

Press 2 to connect to a conference call.

Press 3 to hear some wisdom.

Press 4 to be connected to support.

</Say>

</Gather>

<Say>

I don't understand. Please try again later.

</Say>

<Hangup/>

</Response>
<?php header('Content-Type: text/xml'); ?>

<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say>

Thanks for calling my demo IVR. Please

listen closely as this is the first time

you've heard this menu.

</Say>

<Gather numDigits="1" action="/twiml/process_ivr_menu.php">

<Say>

Press 1 to hear a random sound.

Press 2 to connect to a conference call.

Press 3 to hear some wisdom.

Press 4 to be connected to support.

</Say>

</Gather>

<Say>

I don't understand. Please try again later.

</Say>

<Hangup/>

</Response>
Greeting
<?php header('Content-Type: text/xml'); ?>

<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say>

Thanks for calling my demo IVR. Please

listen closely as this is the first time

you've heard this menu.

</Say>

<Gather numDigits="1" action="/twiml/process_ivr_menu.php">

<Say>

Press 1 to hear a random sound.

Press 2 to connect to a conference call.

Press 3 to hear some wisdom.

Press 4 to be connected to support.

</Say>

</Gather>

<Say>

I don't understand. Please try again later.

</Say>

<Hangup/>

</Response>
Menu
Error Handling
<?php header('Content-Type: text/xml'); ?>

<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say>

Thanks for calling my demo IVR. Please

listen closely as this is the first time

you've heard this menu.

</Say>

<Gather numDigits="1" action="/twiml/process_ivr_menu.php">

<Say>

Press 1 to hear a random sound.

Press 2 to connect to a conference call.

Press 3 to hear some wisdom.

Press 4 to be connected to support.

</Say>

</Gather>

<Say>

I don't understand. Please try again later.

</Say>

<Hangup/>

</Response>
Goodbye.
<?php header('Content-Type: text/xml'); ?>

<?xml version="1.0" encoding="UTF-8"?>

<Response>

<Say>

Thanks for calling my demo IVR. Please

listen closely as this is the first time

you've heard this menu.

</Say>

<Gather numDigits="1" action="/twiml/process_ivr_menu.php">

<Say>

Press 1 to hear a random sound.

Press 2 to connect to a conference call.

Press 3 to hear some wisdom.

Press 4 to be connected to support.

</Say>

</Gather>

<Say>

I don't understand. Please try again later.

</Say>

<Hangup/>

</Response>
Now What?
• What if they press something that's not 1-4?
• What if they press 1-4?
• Need to figure out what to do next
Handle ! 1-4
<?php

require_once __DIR__ . '/../vendor/autoload.php';

session_start();

$digits = $_POST['Digits'] ?? 0;



switch ($digits) {

case 1: // Random sound

case 2: // Conference call

case 3: // Random Phrase

case 4: // Support queue

default:

if (countFailures() >= 3) {

echo bailOnCall();

return;

}

echo badInput();

return;

}
countFailures()
function countFailures($count = null)

{

$badInput = $count ?? $_SESSION[__FUNCTION__] ?? 0;

$badInput++;

$_SESSION[__FUNCTION__] = $badInput;

return $badInput;

}
badInput()
function badInput()

{

header('Content-type: text/xml');

$twiml = new TwilioTwiml();

$twiml->say('That was not a valid selection.');

$twiml->redirect('/twiml/ivr_menu.php');

return $twiml;

}
bailOnCall()
function bailOnCall()

{

header('Content-type: text/xml');

$twiml = new TwilioTwiml();

$twiml->say('Your rotary phone is not compatible
with this app.');

$twiml->say('Goodbye.');

$twiml->hangup();

return $twiml;

}
Call Handler
switch ($digits) {

case 1: // Random sound

echo randomSound();

break;

case 2: // Conference call

echo conferenceCall();

break;

case 3: // Random Phrase

echo fortune();

break;

case 4: // Support queue

echo supportQueue();

break;

default:

...
}
randomSound()
function randomSound()

{

header('Content-type: text/xml');

countFailures(-1);

$sounds = ['gull.mp3', 'lawnmower.mp3',

'monkey.mp3'];

$index = array_rand($sounds);

$twiml = new TwilioTwiml();

$twiml->play('/sounds/' . $sounds[$index]);

$twiml->redirect('/twiml/ivr_menu.php');

return $twiml;

}
Conference Call
function conferenceCall()

{

header('Content-type: text/xml');

$response = new TwilioTwiml();

$response->say('You have joined the conference.');

$dial = $response->dial();

$dial->conference('PHP World');

return $response;

}
fortune()
function fortune()

{

$fortune = `fortune -s`;

header('Content-type: text/xml');

$response = new TwilioTwiml();

$response->sms($fortune);

$response->say($fortune);

return $response;

}
supportQueue()
function supportQueue()

{

header('Content-type: text/xml');

$response = new TwilioTwiml();

if ($_POST['From'] == '<my number>') {

// Support agent

$dial = $response->dial();

$dial->queue('support', ['url' => '/twiml/about_to_connect.php']);

} else {

// Enqueue

$response->enqueue('support');

}



return $response;

}
supportQueue()
function supportQueue()

{

header('Content-type: text/xml');

$response = new TwilioTwiml();

if ($_POST['From'] == '<my number>') {

// Support agent

$dial = $response->dial();

$dial->queue('support', ['url' => '/twiml/about_to_connect.php']);

} else {

// Enqueue

$response->enqueue('support');

}



return $response;

}
Just Scratching the Surface
• Twilio can keep our application informed about
how calls are going
• We can interact with ongoing calls via the REST
API
Questions?
• Twitter: @dstockto
• Joind.in - https://joind.in/talk/e2e2b
20162016

Phone calls and sms from php

  • 1.
    Phone Calls andSMS from PHP PHP World 2016 David Stockton November 16, 2016
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
    How else canwe receive input and produce output?
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 23.
  • 24.
    Let's Send anSMS new TwilioRestClient($config['sid'], $config['token']); Make a client
  • 25.
    Let's Send anSMS $client->messages->create(
 $toNumber,
 array(
 'from' => '+1<purchased#>',
 'body' => $fortune
 )
 );
  • 26.
    All Together $toNumber =$argv[1] ?? '<default #>';
 
 $toNumber = PhpWorld Utility::normalizeNumber($toNumber);
 
 $fortune = $argv[2] ?? `fortune`;
 
 $client->messages->create(
 $toNumber,
 array(
 'from' => '+<purchased #>',
 'body' => $fortune
 )
 );
  • 27.
    How to Use? $php bin/fortune.php $ php bin/fortune.php <destination #> $ php bin/fortune.php <destination #> "Text message from the command line"
  • 28.
  • 29.
  • 30.
    php bin/fortune.php 7206757471"Your account has been created or something."
  • 31.
    What can wedo? • Notifications • Two-Factor Authentication (2FA) • Responses to Queries
  • 32.
    Make a PhoneCall • API Call to Twitter • Twitter contacts URL for instructions
  • 33.
    TwiML • Twilio's MarkupLanguage for controlling phone calls • XML
  • 34.
    TwiML Commands • Say- Read text to the caller • Play - Play an audio file for the caller • Dial - Add another party to the call • Record - Record the caller's voice • Gather - Collect digits the caller types on their keypad • Sms - Send an SMS message during a phone call
  • 35.
    More TwiML • Hangup- Hang up the call • Queue - Add the caller to a queue of callers. • Redirect - Redirect call flow to a different TwiML document. • Pause - Wait before executing more instructions • Reject - Decline an incoming call without being billed. • Message - Send an MMS or SMS message reply
  • 36.
    How Outgoing CallsWork Your App TwilioAPI Call TwiML CalleeTwilio Plays Twiml
  • 37.
    TwiML <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Sayvoice="woman">Your call is very
 important to us, but not so
 important we'll answer it with
 a human. Please leave a message.
 </Say>
 <Record maxLength="20" playBeep="true"/>
 </Response>
  • 38.
    XML <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Sayvoice="woman">Your call is very
 important to us, but not so
 important we'll answer it with
 a human. Please leave a message.
 </Say>
 <Record maxLength="20" playBeep="true"/>
 </Response>
  • 39.
    Root Element <?xml version="1.0"encoding="UTF-8"?>
 <Response>
 <Say voice="woman">Your call is very
 important to us, but not so
 important we'll answer it with
 a human. Please leave a message.
 </Say>
 <Record maxLength="20" playBeep="true"/>
 </Response>
  • 40.
    Commands - Say <?xmlversion="1.0" encoding="UTF-8"?>
 <Response>
 <Say voice="woman">Your call is very
 important to us, but not so
 important we'll answer it with
 a human. Please leave a message.
 </Say>
 <Record maxLength="20" playBeep="true"/>
 </Response>
  • 41.
    <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Sayvoice="woman">Your call is very
 important to us, but not so
 important we'll answer it with
 a human. Please leave a message.
 </Say>
 <Record maxLength="20" playBeep="true"/>
 </Response> Commands - Record
  • 42.
  • 43.
    Let's Make aCall <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Say voice="man">
 Due to inclement weather, school
 will be closed tomorrow. Please
 stay home and stay safe.
 </Say>
 </Response>
  • 44.
    The Full File <?phpheader('Content-Type: text/xml'); ?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Say voice="man" loop="2">
 Due to inclement weather, school
 will be closed tomorrow. Please
 stay home and stay safe.
 </Say>
 </Response>
  • 45.
    Tell Twilio WhoTo Call <?php
 require_once __DIR__ . '/../vendor/autoload.php';
 /** @var TwilioRestClient $client */
 $client = require_once __DIR__ . '/../src/PhpWorld/client.php';
 
 $to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');
 $from = '+<purchased #>';
 
 $options = [
 'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/ school_outage.php',
 ];
 
 $client->calls->create($to, $from, $options);
  • 46.
    Tell Twilio WhoTo Call <?php
 require_once __DIR__ . '/../vendor/autoload.php';
 /** @var TwilioRestClient $client */
 $client = require_once __DIR__ . '/../src/PhpWorld/client.php';
 
 $to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');
 $from = '+<purchased #>';
 
 $options = [
 'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/ school_outage.php',
 ];
 
 $client->calls->create($to, $from, $options);
  • 47.
    Tell Twilio WhoTo Call <?php
 require_once __DIR__ . '/../vendor/autoload.php';
 /** @var TwilioRestClient $client */
 $client = require_once __DIR__ . '/../src/PhpWorld/client.php';
 
 $to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');
 $from = '+<purchased #>';
 
 $options = [
 'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/ school_outage.php',
 ];
 
 $client->calls->create($to, $from, $options);
  • 48.
    Tell Twilio WhoTo Call <?php
 require_once __DIR__ . '/../vendor/autoload.php';
 /** @var TwilioRestClient $client */
 $client = require_once __DIR__ . '/../src/PhpWorld/client.php';
 
 $to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');
 $from = '+<purchased #>';
 
 $options = [
 'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/ school_outage.php',
 ];
 
 $client->calls->create($to, $from, $options);
  • 49.
    Tell Twilio WhoTo Call <?php
 require_once __DIR__ . '/../vendor/autoload.php';
 /** @var TwilioRestClient $client */
 $client = require_once __DIR__ . '/../src/PhpWorld/client.php';
 
 $to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');
 $from = '+<purchased #>';
 
 $options = [
 'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/ school_outage.php',
 ];
 
 $client->calls->create($to, $from, $options);
  • 50.
    Tell Twilio WhoTo Call <?php
 require_once __DIR__ . '/../vendor/autoload.php';
 /** @var TwilioRestClient $client */
 $client = require_once __DIR__ . '/../src/PhpWorld/client.php';
 
 $to = PhpWorldUtility::normalizeNumber($argv[1] ?? '+<default #>');
 $from = '+<purchased #>';
 
 $options = [
 'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/twiml/ school_outage.php',
 ];
 
 $client->calls->create($to, $from, $options);
  • 51.
    Phone and SMS Conversations •Twilio is like a well-behaved HTTP client • It uses sessions • We can use session to remember things about the caller or the conversation
  • 52.
    Phone IVR • Givecallers a menu • Look up information • Connect to people • Solve problems • Give answers
  • 53.
    First TwiML <?php header('Content-Type:text/xml'); ?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Say>
 Thanks for calling my demo IVR. Please
 listen closely as this is the first time
 you've heard this menu.
 </Say>
 <Gather numDigits="1" action="/twiml/process_ivr_menu.php">
 <Say>
 Press 1 to hear a random sound.
 Press 2 to connect to a conference call.
 Press 3 to hear some wisdom.
 Press 4 to be connected to support.
 </Say>
 </Gather>
 <Say>
 I don't understand. Please try again later.
 </Say>
 <Hangup/>
 </Response>
  • 54.
    <?php header('Content-Type: text/xml');?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Say>
 Thanks for calling my demo IVR. Please
 listen closely as this is the first time
 you've heard this menu.
 </Say>
 <Gather numDigits="1" action="/twiml/process_ivr_menu.php">
 <Say>
 Press 1 to hear a random sound.
 Press 2 to connect to a conference call.
 Press 3 to hear some wisdom.
 Press 4 to be connected to support.
 </Say>
 </Gather>
 <Say>
 I don't understand. Please try again later.
 </Say>
 <Hangup/>
 </Response> Greeting
  • 55.
    <?php header('Content-Type: text/xml');?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Say>
 Thanks for calling my demo IVR. Please
 listen closely as this is the first time
 you've heard this menu.
 </Say>
 <Gather numDigits="1" action="/twiml/process_ivr_menu.php">
 <Say>
 Press 1 to hear a random sound.
 Press 2 to connect to a conference call.
 Press 3 to hear some wisdom.
 Press 4 to be connected to support.
 </Say>
 </Gather>
 <Say>
 I don't understand. Please try again later.
 </Say>
 <Hangup/>
 </Response> Menu
  • 56.
    Error Handling <?php header('Content-Type:text/xml'); ?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Say>
 Thanks for calling my demo IVR. Please
 listen closely as this is the first time
 you've heard this menu.
 </Say>
 <Gather numDigits="1" action="/twiml/process_ivr_menu.php">
 <Say>
 Press 1 to hear a random sound.
 Press 2 to connect to a conference call.
 Press 3 to hear some wisdom.
 Press 4 to be connected to support.
 </Say>
 </Gather>
 <Say>
 I don't understand. Please try again later.
 </Say>
 <Hangup/>
 </Response>
  • 57.
    Goodbye. <?php header('Content-Type: text/xml');?>
 <?xml version="1.0" encoding="UTF-8"?>
 <Response>
 <Say>
 Thanks for calling my demo IVR. Please
 listen closely as this is the first time
 you've heard this menu.
 </Say>
 <Gather numDigits="1" action="/twiml/process_ivr_menu.php">
 <Say>
 Press 1 to hear a random sound.
 Press 2 to connect to a conference call.
 Press 3 to hear some wisdom.
 Press 4 to be connected to support.
 </Say>
 </Gather>
 <Say>
 I don't understand. Please try again later.
 </Say>
 <Hangup/>
 </Response>
  • 58.
    Now What? • Whatif they press something that's not 1-4? • What if they press 1-4? • Need to figure out what to do next
  • 59.
    Handle ! 1-4 <?php
 require_once__DIR__ . '/../vendor/autoload.php';
 session_start();
 $digits = $_POST['Digits'] ?? 0;
 
 switch ($digits) {
 case 1: // Random sound
 case 2: // Conference call
 case 3: // Random Phrase
 case 4: // Support queue
 default:
 if (countFailures() >= 3) {
 echo bailOnCall();
 return;
 }
 echo badInput();
 return;
 }
  • 60.
    countFailures() function countFailures($count =null)
 {
 $badInput = $count ?? $_SESSION[__FUNCTION__] ?? 0;
 $badInput++;
 $_SESSION[__FUNCTION__] = $badInput;
 return $badInput;
 }
  • 61.
    badInput() function badInput()
 {
 header('Content-type: text/xml');
 $twiml= new TwilioTwiml();
 $twiml->say('That was not a valid selection.');
 $twiml->redirect('/twiml/ivr_menu.php');
 return $twiml;
 }
  • 62.
    bailOnCall() function bailOnCall()
 {
 header('Content-type: text/xml');
 $twiml= new TwilioTwiml();
 $twiml->say('Your rotary phone is not compatible with this app.');
 $twiml->say('Goodbye.');
 $twiml->hangup();
 return $twiml;
 }
  • 63.
    Call Handler switch ($digits){
 case 1: // Random sound
 echo randomSound();
 break;
 case 2: // Conference call
 echo conferenceCall();
 break;
 case 3: // Random Phrase
 echo fortune();
 break;
 case 4: // Support queue
 echo supportQueue();
 break;
 default:
 ... }
  • 64.
    randomSound() function randomSound()
 {
 header('Content-type: text/xml');
 countFailures(-1);
 $sounds= ['gull.mp3', 'lawnmower.mp3',
 'monkey.mp3'];
 $index = array_rand($sounds);
 $twiml = new TwilioTwiml();
 $twiml->play('/sounds/' . $sounds[$index]);
 $twiml->redirect('/twiml/ivr_menu.php');
 return $twiml;
 }
  • 65.
    Conference Call function conferenceCall()
 {
 header('Content-type:text/xml');
 $response = new TwilioTwiml();
 $response->say('You have joined the conference.');
 $dial = $response->dial();
 $dial->conference('PHP World');
 return $response;
 }
  • 66.
    fortune() function fortune()
 {
 $fortune =`fortune -s`;
 header('Content-type: text/xml');
 $response = new TwilioTwiml();
 $response->sms($fortune);
 $response->say($fortune);
 return $response;
 }
  • 67.
    supportQueue() function supportQueue()
 {
 header('Content-type: text/xml');
 $response= new TwilioTwiml();
 if ($_POST['From'] == '<my number>') {
 // Support agent
 $dial = $response->dial();
 $dial->queue('support', ['url' => '/twiml/about_to_connect.php']);
 } else {
 // Enqueue
 $response->enqueue('support');
 }
 
 return $response;
 }
  • 68.
    supportQueue() function supportQueue()
 {
 header('Content-type: text/xml');
 $response= new TwilioTwiml();
 if ($_POST['From'] == '<my number>') {
 // Support agent
 $dial = $response->dial();
 $dial->queue('support', ['url' => '/twiml/about_to_connect.php']);
 } else {
 // Enqueue
 $response->enqueue('support');
 }
 
 return $response;
 }
  • 69.
    Just Scratching theSurface • Twilio can keep our application informed about how calls are going • We can interact with ongoing calls via the REST API
  • 70.
    Questions? • Twitter: @dstockto •Joind.in - https://joind.in/talk/e2e2b
  • 71.