Friday 28 April 2017

Consuming REST API in PHP Using Guzzle

If you are familiar with Rest API, you must know about HTTP calls created for getting and posting data from the client to the server. What if you wish to create a REST API client in PHP? Your answer would be to go with CURL. CURL is the most widely used method to make HTTP calls but it contains several complicated steps.
Let’s see a simple CURL request in PHP:
$url = “https://api.cloudways.com/api/v1
$resource = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, [‘Accept:application/json, Content-Type:application/json’]);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, ‘GET’);
You need to call the curl_setopt() method to define the header and the particular HTTP verb like GET, POST, PUT, etc. It does look pretty complicated. So, what is a better and robust alternative?
Here comes Guzzle.
Let’s see how Guzzle creates a request:
$client = new GuzzleHttp\Client();
$res = $client->request(‘GET’, ‘https://api.cloudways.com/api/v1’, [
‘headers’ => [
‘Accept’ => ‘application/json’,
‘Content-type’ => ‘application/json’
]])
You could see that it is simple. You just need to initialize the Guzzle client and give HTTP verbs and a URL. After that, pass the array of headers and other options.

Understand the Guzzle Client

Guzzle is a simple PHP HTTP client that provide an easy method of creating calls and integration with web services. It is the standard abstraction layer used by the API to send messages over the server. Several prominent features of Guzzle are:
  1. Guzzle can send both synchronous and asynchronous requests.
  2. It provides a simple interface for building query strings, POST requests, streaming large uploads & downloads, uploading JSON data, etc.
  3. Allows the use of other PSR7 compatible libraries with Guzzle.
  4. Allows you to write environment and transport agnostic code.
  5. Middleware system allows you to augment and compose client behavior.

Install Guzzle In PHP

The preferred way of installing Guzzle is Composer. If you haven’t installed Composer yet, download it from here
Now to install Guzzle, run the following command in SSH terminal:
composer require guzzlehttp/guzzle
This command will install the latest version of Guzzle in your PHP project. Alternatively you can also define it as a dependency in the composer.json file and add the following code in it.
{
 “require”: {
 “guzzlehttp/guzzle”: “~6.0”
 }
}
After that, run the composer install command. Finally you need to require the autoloader and added some more files to use Guzzle:
require ‘vendor/autoload.php’;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Request;
The installation process is over and now it’s time to work with a real example of creating HTTP calls with an API. For the purpose of this article, I will work with Cloudways API.

What You Can Do With the Cloudways API

Cloudways is a managed hosting provider for PHP, Magento, WordPress and many other frameworks and CMS. It has an API that you could use for performing CRUD operations on servers and applications. Check out popular use cases of the Cloudways API to see how you could integrate it into your projects.
In this article, I am going to create HTTP calls to perform specific operations with Guzzle on Cloudways server.

Create the HTTP Requests In Guzzle

As I mentioned earlier, creating HTTP requests in Guzzle is very easy; you only need to pass the base URI, HTTP verb and headers. If there is an authentication layer in the external API, you can also pass these parameters in Guzzle. Similarly, Cloudways API needs email and API key to authenticate users and send the response. You need to sign up for a Cloudways account to get your API credentials.
Let’s start by creating a CloudwaysAPIClient.php file to set up Guzzle for making HTTP calls. I will also create a class and several methods using HTTP calls in them.
The URL of the API does not change so I will use const datatype for it. Later on, I will concatenate it with other URL suffixes to get the response. Additionally, I have declared variables $auth_key,$auth_email which will hold the authentication email and the API key. $accessToken will hold the temporary token which will be renewed every time.
Class CloudwaysAPIClient
{
private $client = null;
const API_URL = “https://api.cloudways.com/api/v1";
var $auth_key;
var $auth_email;
var $accessToken;
public function __construct($email,$key)
{
$this->auth_email = $email;
$this->auth_key = $key;
$this->client = new Client();
}
}

Create a Post Request to get Access Token

The access token will be generated from this URL: https://api.cloudways.com/api/v1/oauth/access_token every time I access the API. This will be set in $url with additional data array which holds auth credentials. Later on, I created a POST request with the base URL and query string. The response will be decoded and access token is saved to be used within the methods.
public function prepare_access_token()
{
try
{
$url = self::API_URL . “/oauth/access_token”;
$data = [‘email’ => $this->auth_email,’api_key’ => $this->auth_key];
$response = $this->client->post($url, [‘query’ => $data]);
$result = json_decode($response->getBody()->getContents());
$this->accessToken = $result->access_token;
}
catch (RequestException $e)
{
$response = $this->StatusCodeHandling($e);
return $response;
}
}
Here the POST request for getting access token is completed. Additionally, If you observed in the exception handling, I declared a method StatusCodeHandling($e), which will take care of the response codes (HTTP codes like 404, 401, 200 etc), and throw a related exception.
public function StatusCodeHandling($e)
{
if ($e->getResponse()->getStatusCode() == ‘400’)
{
$this->prepare_access_token();
}
elseif ($e->getResponse()->getStatusCode() == ‘422’)
{
$response = json_decode($e->getResponse()->getBody(true)->getContents());
return $response;
}
elseif ($e->getResponse()->getStatusCode() == ‘500’)
{
$response = json_decode($e->getResponse()->getBody(true)->getContents());
return $response;
}
elseif ($e->getResponse()->getStatusCode() == ‘401’)
{
$response = json_decode($e->getResponse()->getBody(true)->getContents());
return $response;
}
elseif ($e->getResponse()->getStatusCode() == ‘403’)
{
$response = json_decode($e->getResponse()->getBody(true)->getContents());
return $response;
}
else
{
$response = json_decode($e->getResponse()->getBody(true)->getContents());
return $response;
}
}
The main client class is now completed. I will extend it to create more HTTP requests for different cases.

Create a GET Request to Fetch All Servers

Once the User is authenticated, I can fetch all my servers and applications from Cloudways. /server is the suffix concatenated with the base URI. This time, I will attach the accessToken with Authorization string in Guzzle header to fetch all servers in JSON response. To do this, create a new method:
Public function get_servers()
{
try
{
$url = self::API_URL . “/server”;
$option = array(‘exceptions’ => false);
$header = array(‘Authorization’=>’Bearer ‘ . $this->accessToken);
$response = $this->client->get($url, array(‘headers’ => $header));
$result = $response->getBody()->getContents();
return $result;
}
catch (RequestException $e)
{
$response = $this->StatusCodeHandling($e);
return $response;
}
}
Now create index.php file and include CloudwaysAPIClient.php at the top. Next, I will declare my API key and email, passing it to the class constructor to finally get the servers.
include ‘CloudwaysAPIClient.php’;
$api_key = ‘W9bqKxxxxxxxxxxxxxxxxxxxjEfY0’;
$email = ‘shahroze.nawaz@cloudways.com’;
$cw_api = new CloudwaysAPIClient($email,$api_key);
$servers = $cw_api->get_servers();
echo ‘<pre>’;
var_dump($servers);
echo ‘</pre>’;
Let’s test it in Postman to verify that the information and right response codes are being fetched.
So all my servers hosted on the Cloudways Platforms are being fetched. Similarly, you can create new methods with HTTP calls to get applications, server settings, services and etc.
Let’s create a PUT call to change the label of the server which is cloned-php applications at the moment. But first, I need to get the server ID & label because this information will be used as an argument. To get the server ID, create a foreach loop in the index.php file:
foreach($servers->servers as $server){
echo $server->id;
echo $server->label;
}
Now, if I hit the API, it will fetch the server id and label.

Create a PUT Request to Change Server Label

Now to change the server label, I need to create a PUT call in Guzzle. I will extend the class with a new method. Remember that server id and label are two necessary parameters that will be passed in the method.
public function changelabel($serverid,$label)
{
try
{
$url = self::API_URL . “/server/$serverid”;
$data = [‘server_id’ => $serverid,’label’ => $label];
$header = array(‘Authorization’=>’Bearer ‘ . $this->accessToken);
$response = $this->client->put($url, array(‘query’ => $data,’headers’ => $header));
return json_decode($response->getBody()->getContents());
}
catch (RequestException $e)
{
$response = $this->StatusCodeHandling($e);
return $response;
}
}
Now in the index.php, put this condition beneath the foreach loop.
if($server->id == ‘71265’ && $server->label == ‘Cloned-php applications’){
$label = ‘Cloudways Server’;
$changelabel = $cw_api->changelabel($server->id,$label);
}
When testing this in Postman, I will get the updated server label.

Create a Delete Request to Remove a Server

To delete a server using Cloudways API, I need to create a Delete request in Guzzle through the following method. This is pretty similar to the above method, because it also requires two parameters, server id and label.
public function deleteServer($serverid,$label)
{
try
{
$url = self::API_URL . “/server/$serverid”;
$data = [‘server_id’ => $serverid,’label’ => $label];
$header = array(‘Authorization’=>’Bearer ‘ . $this->accessToken);
$response = $this->client->delete($url, array(‘query’ => $data,’headers’ => $header));
return json_decode($response->getBody()->getContents());
}
catch (RequestException $e)
{
$response = $this->StatusCodeHandling($e);
return $response;
}
}
Try this in Postman or just refresh the page. The server will be deleted.

Final Words

Guzzle is a flexible HTTP client that you could extend as per your requirements. You can also try out new ideas with uploading data, form fields, cookies, redirects and exceptions. You can also create middleware for authentication layer (if needed). All in all, Guzzle is a great option for creating REST API in PHP, without using any frameworks.
If you have any questions or query you can comment below.

0 comments: