Consuming third party APIs with Laravel Resources

For some applications, you may be required to use third-party services or APIs to pull some data, transform that data into the desired response and then deliver it to your client interface.

To do so, you need to find a way to keep consistency within the objects you are going to send from your controllers to your views or your end-user interface.
So, you may need to build a new object or class that represents the desired resource in your application.

You may think “why do I need that?” well, you don’t want to expose all the API response data among your application. Also, you may need to transform some of the fields of that response, etc.
On this article, I’m going to show you an easy way to transform the incoming data from a third party API into a resource in your application that will help you to keep consistency.

Before going further: on this article, I’ll assume you have at least a basic understanding of what is and how to consume an API, how to work with the Laravel framework and some of its components as Eloquent ORM. If you don’t have Idea of what all of this means, you may find challenging some of the concepts, but hey, don’t be discouraged, I’m sure you’ll find some value on this article.

A few things about “Laravel resources”

The ‘API Resources’ where introduced in Laravel 5.5 as a way to “expressively and easily transform your models and model collections into JSON”.

Although this is the official description, and you find this section indexed under the “Eloquent” documentation in the official website, you have to know these resources are not strictly attached to the Eloquent ORM on anyway.

In the most basic sense, a “Resource” allows you to transform a given object into a different one.

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\Resource;

class UserResource extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}

You can learn all about “Resources” by reading the official docs:

Working with third party APIs

When you work with third party APIs, you need to find a way to transform the incoming response into a consistent structure of data.

The laravel news case: Not a long time ago Eric L. Barnes published an article describing how he was using Laravel to build a front-end for the laravel-news website using WordPress as a backend and reading the data from the WordPress API. Here you can read the full article. https://laravel-news.com/wordpress-api-with-laravel

So, having that specific case as an example. Let’s say you have a WordPress repository in your application that pulls the data from the WordPress API.

<?php
class WordpressRepository {
    pubic function getPost($id)
{
$response = $this->apiClient->get(
'post',
$query = ['id' => $id]
);
        // return as array
return json_decode($response, true);
    }
}

Let’s say you receive this object from the WordPress API

// wordpress version 0.1
{
ID: 123
post_title: "some title"
post_content: "some content",
post_author: "joe",
publish_date: "01-01-2001"
}

You can just wrap this response into an array and then use this data on all your controllers or views.

Consistency is the key

Now think for a moment, what will happen if the WordPress API gets updated, and the new version returns an object with a different structure:

// wordpress version 0.1
{
post_id: 123
title: "some title"
content: "some content",
author: "joe",
date: "01-01-2001"
}

Well, that means that now you have to update every reference of $post['post_tile'] for something like $post['title'] in multiple places of your application.

Having an intermediate object will allow you to have the consistency of the data, and in the case the incoming response change, you’ll have to update just a single part of your application to support the new structure, the resource object.

Massaging the data with API resources

As I mentioned before, you can use “Resources” without Eloquent, and I think this example is a good use case for it.
The first thing you need to do is to create a new “Post” resource; you can use artisan to do so:

$ php artisan make:resource Post

<?php
namespace App\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Post extends Resource
{
    public function toArray($request)
    {
        return [
'title' => $this->resource['title'],
'content' => $this->resource['content'],
'slug' => $this->resource['slug']
];
    }
}

Returning single resource instances

Now, following the same example, in your API repository class, you can create a new instance of this resource and then call the resolve() method to return the transformed object (this will return an array).

<?php
class WordpressRepository {
    pubic function getPost($id)
{
$response = $this->apiClient->get(
'post',
$query = ['id' => $id]
);
$data = json_decode($response, true);
return Post::make($data)->resolve();
    }
}

Returning a collection of resources

You can create a dedicated “PostCollection” resource class.

$ php artisan make:resource PostCollection

<?php
namespace App\PublisherPlus\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PostCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return [
            'data' => $this->collection
->map
->toArray($request)
->all(),
            'links' => [
               'self' => 'link-value',
             ],
        ];
    }
}

In this case, 'data' will contain an array of Posts with the same structure that you have defined in your Post resource.

Learn more about “resource collections” here:

In conclusion!

So, if you take a moment to see what “resources” actually are, you may think of them as intermediate objects which purpose would be to adapt the given data to the new, different structured object or array.


So far now, this is just an experiment, I haven’t used this on any production app, so I’m intrested on what you have to say about this idea 😃 — Please leave your comments below.