Blog · Laravel

How to consume external third-party API in Laravel 5

Use Guzzle in Laravel 5 / 6 to call external HTTP APIs from routes, controllers, or a singleton client registered in the service container.

Laravel 5 / 6GuzzleHTTP API

Getting started

In this tutorial, we'll be learning how to consume external / third-party APIs using Guzzle in Laravel 5 and Laravel 6.

What is Guzzle Client?

Guzzle is a PHP HTTP client that makes it easy to send or retrieve HTTP requests.

  • It provides the interface where you can send both synchronous and asynchronous requests.
  • It uses PSR-7 interfaces for streams, requests, and responses.
  • The middleware system allows you to augment and compose client behavior.

I am assuming you have already set up the Laravel project. If not, you can follow this guide: Install Laravel 5 in Ubuntu 16.04 and 18.04 (see the official Laravel installation documentation for your environment).

Also, make sure Composer is installed on your system.

Install Guzzle Client in Laravel project

To install Guzzle, enter the following command in your terminal:

composer require guzzle/guzzle:~3.9

Method 1. Consume API from route

To call the external API from the Laravel route, copy and paste the following code in your routes/web.php:

# routes/web.php

<?php
use GuzzleHttp\Client;

Route::get('/json-api', function() {
	$client = new Client();

	$response = $client->request('GET', 'https://desertebs.com/api/dummy/posts');
	$statusCode = $response->getStatusCode();
	$body = $response->getBody()->getContents();

	return $body;
});

Import the Guzzle client, create a new instance, and make the request with the request function. The first parameter is GET and the second is the URL.

  • $response->getStatusCode() returns the HTTP status code.
  • $response->getBody()->getContents() returns the body contents.

Method 2. Consume API from the controller

To call the third-party API from the controller, first create a route. Copy and paste the following into your routes/web.php file:

# routes/web.php

Route::get('json-api', 'ApiController@index');

Next, create ApiController. From your project directory, run:

php artisan make:controller ApiController

This creates ApiController under app/Http/Controllers. Add an index method and put the logic to consume the API:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use GuzzleHttp\Client;

class ApiController extends Controller
{
    public function index()
    {
    	$client = new Client();
    	$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/todos/1');
    	$statusCode = $response->getStatusCode();
    	$body = $response->getBody()->getContents();

    	return $body;
    }
}

What we did here:

  • use GuzzleHttp\\Client — import Guzzle Client.
  • new Client() — create a new instance of the Guzzle client.
  • Call request() with two parameters: the HTTP method (GET) and the URL.
  • getStatusCode() — HTTP status code.
  • getBody()->getContents() — response body contents.

Method 3. Register the API with the service container

In this section, we'll use the singleton method to consume the API.

Singleton: it allows one instance of itself to be reused.

We'll use the singleton with the Laravel service container so it resolves only once; subsequent calls return the same instance.

Let's get started.

Open and edit your AppServiceProvider.php in app/Providers and add the following:

# app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use GuzzleHttp\Client;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        $baseUrl = env('DESERT_EBS_BASE_URL');

        $this->app->singleton('GuzzleHttp\Client', function($api) use ($baseUrl) {
            return new Client([
                'base_uri' => $baseUrl,
            ]);
        });
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}

$baseUrl = env('DESERT_EBS_BASE_URL') reads the base URL from .env.

Open your .env file and add:

# .env

DESERT_EBS_BASE_URL=https://desertebs.com/api

Note: If you use php artisan serve, restart it after changing .env so the new variables load.

Next, create a helper class that talks to the endpoint. Create a new file under app:

# app/Util/Post.php

<?php
namespace App\Util;

use GuzzleHttp\Client;

class Post
{
	protected $client;

	public function __construct(Client $client)
	{
		$this->client = $client;
	}

	public function all()
	{
		return $this->endpointRequest('/dummy/posts');
	}

	public function findById($id)
	{
		return $this->endpointRequest('/dummy/post/'.$id);
	}

	public function endpointRequest($url)
	{
		try {
			$response = $this->client->request('GET', $url);
		} catch (\Exception $e) {
            return [];
		}

		return $this->response_handler($response->getBody()->getContents());
	}

	public function response_handler($response)
	{
		if ($response) {
			return json_decode($response);
		}
		
		return [];
	}
}

Import this helper in your controller: use App\\Util\\Post

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Util\Post;

class ApiController extends Controller
{
	protected $post;

    public function __construct(Post $post)
    {
    	$this->post = $post;
    }

    public function index()
    {
    	// Get all the post
    	$posts = $this->post->all();

    	return view('someview', compact('posts'));
    }

    public function show($id)
    {
    	$post = $this->post->findById($id);

    	return view('someview', compact('post'));
    }
}

You can dd($posts) to inspect the response.