Using Guzzle http client to send api requests to Laravel API.
Published: 2021-09-22 07:17:17

<b>Introduction</b>
A <b>Guzzle</b> is a PHP HTTP client that makes it easy to send HTTP requests with data, headers and trivial to integrate with web services. Guzzle is a simple interface for building query strings, POST requests, streaming large uploads, streaming large downloads, using HTTP cookies, uploading JSON data, etc.

Basically, GuzzleHttp helps to make requests to external api to get, post, update or delete data. Assuming you already have your api(could have been implemented in any language), I will demonstrate how to use it to make post, get, update and delete requests.

First of all, we need to install guzzlehttp in our laravel project using composer by running the command below in our project root directory.
```php
composer require guzzlehttp/guzzle
```
In your laravel class or controller, import GuzzleHttp Client as follows;
```php
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Psr7\Request;
```
<b>GET METHOD</b>
```php
public static function getHttpHeaders(){
		
	   $bearerToken = 'your-bearer-token';
	   $headers    =   [
			'headers' => [
			'Content-Type' => 'application/json',
		      'Authorization' => 'Bearer ' .$bearerToken,
			],
		    'http_errors' => false,
		];
		return $headers;
	}

public static function GetDataByEndPoint($endPoint)
{

	$baseApiUrl = EndPoints::$BASE_URL;
        $url = $baseApiUrl . $endPoint;
	$client = new \GuzzleHttp\Client(self::getHttpHeaders());
	$response = $client->get($url, ['verify' => false]);

    $resp['statusCode'] = $response->getStatusCode();
    $resp['bodyContents'] = $response->getBody()->getContents();
	return $resp;
}
```
In the above code snippet, I have a static method <b>getHttpHeaders()</b> from which I configure and return Http request headers which I pass to the Guzzle Http Client when making requests to the API. Setting the option <b>'http_errors'</b> to false, disables Http Exceptions so that you can access status code on the response from the API.

<b>GetDataByEndPoint</b> is a static method which takes in an endpoint as a parameter from which to fetch data. With in the body of the method, I use a static variable <b>$BASE_URL</b> which is the api url from my custom class named <b>EndPoints</b> on which I concatenate the endpoint.
 
I create an instance of GuzzleHttp Client <b>$client</b>. The url is then passed to the get method on the $client instance to return response from the api. getContents() on getBody() is used to return contents from the api while getStatusCode() is used to return statusCode on the response object.

 <b>POST METHOD</b>
```php
public static function PostDataByEndPoint($endPoint, $body)
{
	$baseApiUrl = EndPoints::$BASE_URL;
        $url = $baseApiUrl . $endPoint;
	$client = new \GuzzleHttp\Client(self::getHttpHeaders());
	$request = $client->request('POST',$url, ['form_params' => 
         $body]);
	$response = $request->getBody()->getContents();
	return $response;
}
```
In the method <b>PostDataByEndPoint</b> above, the difference from the get method is that I pass body or data which can be an array or json. 

<b>NOTE:</b> You can also use ['body'=> json_encode($body)] instead of ['form_params' => $body] basing on your api input needs.

<b>PUT METHOD</b>
```php
public static function PutDataByEndPoint($endPoint, $body)
{
	$baseApiUrl = EndPoints::$BASE_URL;
        $url = $baseApiUrl . $endPoint;
	$client = new \GuzzleHttp\Client(self::getHttpHeaders());
	$request = $client->request('PUT',$url, ['form_params' => $body]);
	$response = $request->getBody()->getContents();
	return $response;
}
```
In <b>PutDataByEndPoint</b> method, I pass the endpoint and body of data as well just like in the post method above.

<b>DELETE METHOD</b>
```php
 public static function deleteDataByEndPoint($endPoint, $body){
	$baseApiUrl = EndPoints::$BASE_URL;
         $url = $baseApiUrl . $endPoint;
	$client = new \GuzzleHttp\Client(self::getHttpHeaders());
	$request = $client->delete($url, ['body' => 
        json_encode($body)]);
	$response = $request->getBody()->getContents();
	return $response;

}
```
The above method <b>deleteDataByEndPoint</b>, it takes in an endpoint and then body(can be an array containing id that will uniquely identify a record to be deleted from the data source).

<b>NOTE:</b> All the methods above can be used anywhere in any of your controllers or classes meaning that they are reusable.

<b>Usage of the get method GetDataByEndPoint</b>
```php
  $endPoint = '/users';
  $resp = ApiRequestResponse::GetDataByEndPoint($endPoint);
  $apiResult = json_decode($resp, true);
  $data = $apiResult['data'];
```
<b>Usage of the post method PostDataByEndPoint</b>
```php
 $reqParams = array('first_name' => $first_name,
                    'last_name' => $last_name,
                    'address' => $address,
                    'age' => $age,
             );

$endPoint = '/users';
$resp = ApiRequestResponse::PostDataByEndPoint($endPoint, $reqParams);
$apiResult = json_decode($resp, true);
$statusCode = $apiResult['statusCode'];
$message = $apiResult['message'];
```
<b>Usage of the put method PutDataByEndPoint</b>
```php
 $reqParams = array('id' => $id,
                    'first_name' => $first_name,
                    'last_name' => $last_name,
                    'address' => $address,
                    'age' => $age,
             );
$endPoint = '/users';
$resp = ApiRequestResponse::PutDataByEndPoint($endPoint, $reqParams);
$apiResult = json_decode($resp, true);
$statusCode = $apiResult['statusCode'];
$message = $apiResult['message'];
```
<b>Usage of the delete method deleteDataByEndPoint</b>
```php
$reqParams = array('id' => $id,
                    'user' => $request->user()->name,
             );
$endPoint = '/users';
$resp=ApiRequestResponse::deleteDataByEndPoint($endPoint, $reqParams);
$apiResult = json_decode($resp, true);
$statusCode =$apiResult['statusCode'];
$message =$apiResult['message'];
```
<b>EndPoints class</b>
```php
<?php
namespace App\Helpers;
class EndPoints {
public static $BASE_URL = 'placehereyourapibaseurl'; // API URL
}
```

<b>NOTES:</b> 
<b>1.</b>The methods GetDataByEndPoint, PostDataByEndPoint, PutDataByEndPoint, deleteDataByEndPoint can be given names of your choice and <b>ApiRequestResponse</b> is the class that contains these methods.
<b>2.</b> If you want to pass full urls instead of the endpoints, you can go ahead and do that. That means that you forego using EndPoints class to get API url. But remember using EndPoints class helps you to configure your api url at once. The other approach of passing full urls means that you have to edit it everywhere in your classes whenever the api url changes which is not a good practice.

That's the end of today's tutorial, hope it helps you!
You can leave comment basing on how you have seen this post. Thank you.