A significant number of web applications depend on external APIs when integrating third-party services. Due to maintenance or ongoing development, they may occasionally be unavailable during development.
In situations like these, mock APIs are helpful in testing, because they allow developers to continue integrating against the service. Alternatively, there may be a price per API request, so simulating API responses during development might be crucial to minimizing cost.
In this short tutorial, you will learn how to mock Twilio's Lookup API.
Among other things, the Twilio Lookup API enables customers to access phone number data, carrier details, and caller names attached to phone numbers. It also supports phone number validation and formatting. You can see a sample response from the API is available below.
{
"calling_country_code": "1",
"country_code": "US",
"phone_number": "+14159929960",
"national_format": "(415) 992-9960",
"valid": true,
"validation_errors": null,
"caller_name": null,
"sim_swap": null,
"call_forwarding": null,
"live_activity": null,
"line_type_intelligence": null,
"identity_match": null,
"reassigned_number": null,
"sms_pumping_risk": null,
"url": "https://lookups.twilio.com/v2/PhoneNumbers/+14159929960"
}
The first thing to do is to create the project directory, where you store your PHP projects, and to switch into it. To do that, run the commands below.
mkdir lookup
cd lookup
The structure of the application is simplistic, consisting of two directories: app and public. The controller class named Lookup.php, which manages the backend logic before passing it to the front end, is located in the app directory. The front end is located in the public directory.
To create the core directory structure, run the command below.
mkdir -p \
app/Twilio \
public/
Use the following commands if you're using Microsoft Windows:
mkdir app/Twilio
mkdir public
The next thing to do is to add all of the dependencies that the project needs. The application will run on the Slim framework and PHP’s version of Google’s phone number library. Run the command below to install these dependencies.
composer require --with-all-dependencies \
giggsey/libphonenumber-for-php \
selective/basepath \
slim/psr7 \
slim/slim
You will need to add a PSR-4 Autoloader configuration so that the classes created in this tutorial will be available throughout the application. To do this, in composer.json add the JSON snippet below after the already existing code.
"autoload": {
"psr-4": {
"App\\": "app"
}
}
Then, run the following command to update Composer's autoloader file (vendor/autoload.php).
composer dump-autoload
Now that all the dependencies are installed, the next step is to create the class that will return the mock data. To do that, create a new file named Lookup.php in the app/Twilio directory. Then, paste the code below into the new file.
<?php
namespace App\Twilio;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberUtil;
class Lookup
{
public array $data = [];
public function fetch(string $number)
{
$phoneUtil = PhoneNumberUtil::getInstance();
$phone_number = $phoneUtil->parse($number);
$this->data = [
'calling_country_code' => $phone_number->getCountryCode(),
'country_code' => $phoneUtil->getRegionCodeForNumber($phone_number),
'phone_number' => $phoneUtil->format($phone_number, PhoneNumberFormat::E164),
'national_format' => $phoneUtil->format($phone_number, PhoneNumberFormat::NATIONAL),
'valid' => $phoneUtil->isValidNumber($phone_number),
'validation_errors' => $this->validationResult($phoneUtil->isPossibleNumberWithReason($phone_number)),
'caller_name' => null,
'sim_swap' => null,
'call_forwarding' => null,
'live_activity' => null,
'line_type_intelligence' => null,
'identity_match' => null,
'url' => $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']
];
return json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
private function validationResult($reason): string
{
return match ($reason) {
0 => 'NULL',
1 => 'INVALID_COUNTRY_CODE',
2 => 'TOO_SHORT',
3 => 'TOO_LONG',
};
}
}
The class has a single property, named $data
, which is an array used to hold any data returned from the request. It has two methods: fetch()
and validationResult()
. The fetch()
method returns the data to the user once the method is invoked. The isPossibleNumberWithReason()
method of the phone library is a method that validates the given number and returns integers from 0-3. The validationResult()
method replaces these integer codes with their corresponding human-readable codes since the libphonenumber
package returns the validation result as an integer.
Check out the phone library documentation to find out more.
The most crucial part of the application has now been created. All that is left is bootstrapping the Slim application and testing it. To do so, create a new file named index.php in the public directory. Then, paste the code below into the file.
<?php
use App\Twilio\Lookup;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Selective\BasePath\BasePathMiddleware;
use Slim\Factory\AppFactory;
require_once __DIR__ . '/../vendor/autoload.php';
$app = AppFactory::create();
$app->get('/phonenumbers/{number}',
function (Request $request, Response $response, array $param) {
$data = new Lookup();
$response
->getBody()
->write($data->fetch($param['number']));
return $response
->withHeader('content-type', 'application/json')
->withStatus(200);
});
$app->run();
The code imports the required classes and initializes the Slim application with a single route. The route is restricted to handling GET requests. It receives a number which is passed to Lookup
's fetch()
method, then the result is returned. Finally, the application is launched, by calling its run()
method.
With the application complete it's time to run it with PHP’s built-in web server and test it.
php -S localhost:8000 -t public
For testing, run the curl command line below after replacing <<PHONE NUMBER>>
with a valid E.164 formatted phone number.
curl -i -H "Accept: application/json" \
-H "Content-Type: application/json" \
-X GET http://localhost:8000/phonenumbers/<<PHONE NUMBER>>
Feel free to use another tool, such as Postman, instead of curl to test the code.
This should return a response similar to the following.
HTTP/1.1 200 OK
Host: localhost:8000
Date: Tue, 04 Jul 2023 12:54:08 GMT
Connection: close
X-Powered-By: PHP/8.2.0
content-type: application/json
{
"calling_country_code": 234,
"country_code": "NG",
"phone_number": "+2349000080000",
"national_format": "0900 008 0000",
"valid": false,
"validation_errors": "NULL",
"caller_name": null,
"sim_swap": null,
"call_forwarding": null,
"live_activity": null,
"line_type_intelligence": null,
"identity_match": null,
"url": "localhost:8000/phonenumbers/+2349000080000"
}
Since the phone number used in this sample is invalid, you can swap it out with your own in the URL.
Mocking plays an essential part in development, and in this tutorial we went through how to mock Twilio's Lookup API. However, given the mockup's numerous limitations, it is important to note that this should only be used in lieu of the actual Lookup API during development, rather than as a replacement.
Happy building!
Prosper is a freelance Laravel web developer and technical writer that enjoys working on innovative projects that use open-source software. When he's not coding, he searches for the ideal startup opportunity to pursue. Find him on Twitter and Linkedin.
"Look Up Klosterhof Leipzig" by Tenzin Peljor is licensed under the CC BY-SA 2.0.
Also published here.