DEV Community

Kingsconsult
Kingsconsult

Posted on • Updated on

How to consume RESTful APIs in Laravel 8 and Laravel 7

Today, I am going to show you how to consume RESTful APIs, in my previous post I discuss How to Create a Secure CRUD RESTful API in Laravel 8 and 7 Using Laravel Passport, the article teaches you how to create a RESTful API and also securing the API with Passport, Laravel Passport is the official OAuth2 server for Laravel apps. It provides you with a full OAuth2 server implementation.
But in this article, we are only going to be discussing how to consume external API. Why some APIs are authenticated which will require providing a token in order to access the API, others are not authenticated, which means you can access the API without a token.
This article will show you how to implement the two instances. We are going to be using the code from my previous article Laravel 8 CRUD App, A simple guide, this is the GitHub repo for the code snippets.

Click on my profile to follow me to get more updates.

Step 1: Setup the app

  1. git clone https://github.com/Kingsconsult/laravel_8_crud.git
  2. cd laravel_8_crud/
  3. composer install
  4. npm install
  5. cp .env.example .env
  6. php artisan key:generate
  7. Add your database config in the .env file (you can check my articles on how to achieve that)
  8. php artisan migrate
  9. php artisan serve (if the server opens up, http://127.0.0.1:8000, then we are good to go) localhost
  10. Navigate to http://127.0.0.1:8000/projects

Step 2: Make sure Guzzle package is installed

By default, Laravel automatically includes this Guzzle as a dependency when you install Laravel, check your composer.json, if it is one of the required dependency, if you did not see it, or you want to update

composer require guzzlehttp/guzzle

Step 3: Create routes

Modify the routes/web.php file to this

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProjectController;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

Route::get('/', function () {
    return view('welcome');
});

Route::prefix('projects')->group(function () {
    Route::get('apiwithoutkey', [ProjectController::class, 'apiWithoutKey'])->name('apiWithoutKey');
    Route::get('apiwithkey', [ProjectController::class, 'apiWithKey'])->name('apiWithKey');
});


Route::resource('projects', ProjectController::class);
Enter fullscreen mode Exit fullscreen mode

We added two get routes, one for an API without key (unauthorized) and another with key (authorized).

Step 4: Create Controller methods

In our routes, we indicate that we have two more routes, so we need to write the methods, go to app/Http/Controller/ProjectController.php, and add the following methods
First, call the Guzzle class before the controller class, directly under the namespace

use GuzzleHttp\Client;


    public function apiWithoutKey()
    {
        $client = new Client(); //GuzzleHttp\Client
        $url = "https://api.github.com/users/kingsconsult/repos";


        $response = $client->request('GET', $url, [
            'verify'  => false,
        ]);

        $responseBody = json_decode($response->getBody());

        return view('projects.apiwithoutkey', compact('responseBody'));
    }

    public function apiWithKey()
    {
        $client = new Client();
        $url = "https://dev.to/api/articles/me/published";

        $params = [
            //If you have any Params Pass here
        ];

        $headers = [
            'api-key' => 'k3Hy5qr73QhXrmHLXhpEh6CQ'
        ];

        $response = $client->request('GET', $url, [
            // 'json' => $params,
            'headers' => $headers,
            'verify'  => false,
        ]);

        $responseBody = json_decode($response->getBody());

        return view('projects.apiwithkey', compact('responseBody'));
    }
Enter fullscreen mode Exit fullscreen mode

Explanation

  1. I instantiate the client class from guzzle.
  2. I assign the API URL to a variable (I used GitHub API for my public repositories, this is a public API that fetches one's public GitHub repositories), this API does not require a token for authorization.
  3. I use the request method of the client, it accepts 3 parameters ($method, $url, $options), the $options is where we pass our token if the API requires one, also I passed another option, verify, to be false.
  4. Finally, I convert my response to a json format, so I can pass it to the view.

The second method is for an API that requires authorization, I used dev.to API, this API fetches all my published articles and also all the stats for each article, I passed the api key to the options, I assigned it to a variable call headers.

Step 5: Create the views

I created separate views for the two API

resources/views/projects/apiwithoutkey.blade.php

@extends('layouts.app')

@section('content')

<style>


</style>
<div class="row mb-3">
    <div class="col-lg-12 margin-tb">
        <div class="text-center">
            <h2>Github Public Repository</h2>
            <a class="btn btn-primary" href="{{ route('projects.index') }}" title="Go back"> <i class="fas fa-backward fa-2x"></i> </a>
        </div>
    </div>
</div>



<div class="container-fluid mb-5" style="margin-bottom: 150px !important">
    <div class="row mr-4">
        @foreach ($responseBody as $response)

        <div class="col-xl-3 col-md-6 mb-4 hvr-grow ">
            <a href="{{ $response->html_url }}" class="text-muted">
                <div class="card shadow  py-0 rounded-lg ">
                    <div class="card-body py-2 px-2">
                        <div class="row no-gutters align-items-center">
                            <div class="col mr-2">
                                <div class=" font-weight-bold mb-4 mt- 2 text-primary text-center text-uppercase mb-1">
                                    {{ $response->name }}
                                </div>
                                <div class="h6 mb-0 text-gray-800 text-center">{{ $response->description }}
                                    @if ($response->description == null)
                                    {{ $response->name }}
                                    @endif
                                </div>
                            </div>
                        </div>

                        <div style="position: absolute; bottom: 0" class="mb-2"> <strong>
                                <hi>Language : {{ $response->language }}
                            </strong></hi>
                        </div>
                    </div>
                </div>
            </a>
        </div>
        @endforeach
    </div>
</div>

@endsection
Enter fullscreen mode Exit fullscreen mode

resources/views/projects/apiwithkey.blade.php

@extends('layouts.app')

@section('content')

<style>


</style>
<div class="row mb-3">
    <div class="col-lg-12 margin-tb">
        <div class="text-center">
            <h2>Dev.to Article stats</h2>
            <a class="btn btn-primary" href="{{ route('projects.index') }}" title="Go back"> <i class="fas fa-backward fa-2x"></i> </a>
        </div>
    </div>
</div>



<div class="container-fluid mb-5" style="margin-bottom: 150px !important">
    <div class="row mr-4">
        @foreach ($responseBody as $response)

        <div class="col-xl-3 col-md-6 mb-4 hvr-grow ">
            <div class="card shadow  py-0 rounded-lg ">
                <div class="card-body py-2">
                    <div class="row no-gutters align-items-center">
                        <div class="col mr-2">
                            <a href="{{ $response->url }}" class="text-muted">
                                <div class=" font-weight-bold mb-2 mt-2 text-primary text-center text-uppercase mb-1">
                                    {{ Str::limit($response->title, 45) }}

                                </div>
                            </a>
                            <div class="h6 mb-0 text-gray-800 text-center">
                                {{ Str::limit($response->description, 100) }}
                            </div>
                        </div>
                    </div>
                    <div style="position: absolute; bottom: 0" class="mb-2">
                        <hi>Page Views: <strong>{{ number_format($response->page_views_count) }}</strong></hi>
                        <hi class="ml-3"> Reactions: <strong>{{ $response->positive_reactions_count }} </strong></hi>
                    </div>
                </div>
            </div>
        </div>
        @endforeach
    </div>
</div>

@endsection
Enter fullscreen mode Exit fullscreen mode

Testing
Go to the index page of projects http://127.0.0.1:8000/projects
http://127.0.0.1:8000/projects

http://127.0.0.1:8000/projects/apiwithkey
API with key

http://127.0.0.1:8000/projects/apiwithoutkey
API without key

You can get the complete code from the repo.
Follow me for more of my articles, you can leave comments, suggestions, and reactions

click the link to view my profile and follow me

Visit my other posts

Top comments (6)

Collapse
 
tassadar45 profile image
Archivillano Porkazoid

Hi, how would be the best way in laravel, to make a form that sends data to a crud restapi with json through post, and put for the create and update functions?
I mean there is a lot of tutorials on how to consume restful services using GET to make a query and making tables, but there's nothing on using POST, PUT and DELETE to create, update and delete.

Collapse
 
msnmongare profile image
Sospeter Mongare

Hi @tassadar45 , Which API gives you the access to update their API or create records. If given endpoints for creating and updating , then it is possible

Collapse
 
jskogsta profile image
Jorgen Skogstad • Edited

Got any thoughts as to how that can be extended consuming API's that have to be authenticated with a token similar to github.com/WildApricot/ApiSamples/... ?

Essentially fulfilling the same process as this code?:

$waApiClient = WaApiClient::getInstance();

$waApiClient->initTokenByApiKey('put_your_apikey_here');

$account = getAccountDetails();
$accountUrl = $account['Url'];

$contactsResult = getContactsList(); 
$contacts =  $contactsResult['Contacts'];

foreach($contacts as $contact) {
   echo '<br />';
   echo sprintf("#%d - %s", $contact['Id'], $contact['DisplayName']);
}

function getAccountDetails()
{
   global $waApiClient;
   $url = 'https://api.wildapricot.org/v2/Accounts/';
   $response = $waApiClient->makeRequest($url); 
   return  $response[0]; // usually you have access to one account
}

function getContactsList()
{
   global $waApiClient;
   global $accountUrl;
   $queryParams = array(
      '$async' => 'false', // execute request synchronously
      '$top' => 10, // limit result set to 10 records
      '$filter' => 'Member eq true', // filter only members
      '$select' => 'First name, Last name'
   ); // select only first name and last name to reduce size of json data
   $url = $accountUrl . '/Contacts/?' . http_build_query($queryParams);
   return $waApiClient->makeRequest($url);
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
wandieinnocents profile image
WENAREEBA INNOCENT

This has been helpful , had to make modifications , very good foundation of consuming apis.

Collapse
 
geekabel profile image
Godwin

What about put , delete, post request?

Collapse
 
benjaminv profile image
benjaminv

Accidentally found the link in the repo readme.md as https://dev.to/kingsconsult/laravel-8-crud-bi9