Generating Resources

The make:resource Assistant command may be used to create a resource class. Resources are placed in your application's app/Http/Resources directory by default. @ostro/http/resources/json/jsonResource is a resource that extends the @ostro/http/resources/json/jsonResource class:

node assistant make:resource UserResource

Resource Collections

In addition to developing resources that convert individual models, you can also create resources that transform collections of models. This allows you to add links and other meta information related to a whole collection of a specific resource in your JSON answers.

When establishing a resource, use the —collection parameter to build a resource collection. Alternatively, inserting the word Collection in the resource name tells OstroJS to construct a collection resource. The @ostro/http/resources/json/resourceCollection class is extended by collection resources:

node assistant make:resource User --collection

node assistant make:resource UserCollection

Concept Overview

Let's take a high-level look at how resources are utilised in OstroJS before digging into all of the choices accessible to you when developing resources. A resource class denotes a single model that must be converted to a JSON representation. Here's an example of a UserResource resource class:

const jsonResource = require("@ostro/http/resources/json/jsonResources")
class UserResource extends jsonResource {

    /**
     * Transform the resource into an array/object.
     *
     */
    static toObject(data) {
        return {
            'id' : data.id,
            'name' : data.name,
            'email' : data.email,
            'created_at' : data.created_at,
            'updated_at' : data.updated_at,
        }
    }

}

module.exports = UserResource;

Every resource class has a toArray function that produces an array of characteristics that should be converted to JSON when a route or controller method returns the resource.

It's worth noting that model properties may be accessed straight from the this variable. This is because, for convenience, a resource class will automatically proxy property and method access to the underlying model. A route or controller can return the resource after it has been defined. The resource's function Object() { [native code] } accepts the underlying model instance:

const UserResource = require('~/app/http/resources/userResource');
const User = require('~/app/models/user');

Route.get('/user/:id', async function ({ response, params }) {
    response.send(new UserResource(await User.findOrFail(params.id)));
});

Resource Collections

When establishing the resource instance in your route or controller, utilise the collection method offered by your resource class if you're returning a collection of resources or a paginated response:

const UserResource = require('~/app/http/resources/userResource');
const User = require('~/app/models/user');

Route.get('/user/:id', async function ({ response, params }) {
    response.send(UserResource.collection(await User.all()));
});

It's possible that your resource collection will be returned from a route or controller after you've defined it:

const UserResource = require('~/app/http/resources/userResource');
const User = require('~/app/models/user');

Route.get('/user/:id', async function ({response,params}) {
    response.send(UserResource.collection(await User.all()));
});

Writing Resources

In essence, resources are straightforward. They merely have to convert a model into an array. As a result, each resource has a toArray function that converts your model's characteristics into an API-friendly array that can be returned from your app's routes or controllers:

const jsonResource = require("@ostro/http/resources/json/jsonResources")
class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array/object.
     *
     */
    static toObject(data) {
        return {
            'id' : data.id,
            'name' : data.name,
            'email' : data.email,
            'created_at' : data.created_at,
            'updated_at' : data.updated_at,
        }
    }
}

module.exports = UserResource

A resource can be returned directly from a route or controller once it has been defined:

const UserResource = require('~/app/http/resources/userResource');
const User = require('~/app/models/user');

Route.get('/user/:id', async function ({ response, params }) {
    response.send(new UserResource(await User.findOrFail(params.id)));
});

Relationships

You can add related resources to the array produced by your resource's toArray function if you want to include them in your answer. In this example, we'll utilise the collection method of the PostResource resource to add the user's blog entries to the resource response:

const PostResource = require('~/app/http/resources/postResource');

/**
 * Transform the resource into an array / object.
 *
 */
static toObject(data) {
    return {
        'id' : data.id,
        'name' : data.name,
        'email' : data.email,
        'posts' : PostResource.collection(data.posts),
        'created_at' : data.created_at,
        'updated_at' : data.updated_at,
    };
}

Resource Collections

While resources convert a single model to an array, resource collections do the same for a group of models. However, because all resources include a collection function to construct a "ad-hoc" resource collection on the fly, it is not required to declare a resource collection class for each of your models:

const UserResource = require('~/app/http/resources/userResource');
const User = require('~/app/models/user');

Route.get('/user/:id', async function ({ response, params }) {
    response.send(UserResource.collection(await User.all()));
});

While resources convert a single model to an array, resource collections do the same for a group of models. However, because all resources include a collection function to construct a "ad-hoc" resource collection on the fly, it is not required to declare a resource collection class for each of your models:

const ResourceCollection = require("@ostro/http/resources/json/ResourceCollection")

class UserCollection extends ResourceCollection {

    /**
     * Transform the resource collection into an array / object.
     *
     */
    static toObject(data) {
        return {
            'data' : data,
            'links' : {
                'self' : 'link-value',
            },
        };
    }
}

module.exports = UserCollection

Resource collections, like solitary resources, can be returned directly from routes or controllers:

const UserResource = require('~/app/http/resources/userResource');
const User = require('~/app/models/user');

Route.get('/user/:id', async function ({ response, params }) {
    response.send(new UserResource(await User.all()));
});

Introduction

You may require a transformation layer between your Eloquent models and the JSON replies that are actually returned to your application's users when constructing an API. For example, you could want to show some properties to a subset of users but not to others, or you might want to always include certain relationships in your models' JSON representation. Eloquent's resource classes make it simple and expressive to convert your models and model collections to JSON.

Of course, you can always use the toJson methods to convert Eloquent models or collections to JSON; but, Eloquent resources allow more comprehensive and robust control over the JSON serialisation of your models and relationships.