Laravel API Resources: How to remove meta and links property from ResourceCollection

113
Share:
laravel-api-resources-how-to-remove-meta-and-links-property-from-resourcecollection

The Two Words of Web Development

The current state of web development seems to be divided into two worlds: front-end and back-end. Although there are many full-stack developers, project managers usually split their team to satisfy their client timeline. Back-end developers will quickly deliver the API and front-end developers will focus on the user interface.

As a back-end developer myself, I would finish my tasks quickly if I have the API specifications before starting my development things. I believe this is also the case for front-end developers. Once they have the API specifications, they could use valid dummy data. Later on, when we're ready to deliver the MVC, we have small to zero adjustments other than changing the configuration.

Laravel API Backend

When building an API in Laravel, sometimes we may need to transform our Eloquent models to conform with the API specification. For example, we may wish to display certain attributes for a subset of users and not others, or remove some of them at all. Eloquent's resource classes allow us to expressively and easily transform our models and model collections into JSON. For example, consider this UserResource class:

class UserResource extends JsonResource
{

// ... skipped

public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
];
}
}

When we call it, it will respond with this response:

{
"data": [
{
"id": 8,
"name": "Prof. Camren Lehner",
"email": "[email protected]"
},

... skipped

{
"id": 17,
"name": "Miss Susana Crist",
"email": "[email protected]"
}
],
"links": {
"first": "http://localhost:8080/api/v1/users?page=1",
"last": "http://localhost:8080/api/v1/users?page=10",
"prev": null,
"next": "http://localhost:8080/api/v1/users?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"path": "http://localhost:8080/api/v1/users",
"per_page": 10,
"to": 10,
"total": 100
}
}

If we would like to add a field from users table called username, we just need to update our UserResource class to:

class UserResource extends JsonResource
{

// ... skipped

public function toArray($request)
{
return [
'id' => $this->id,
'username' => $this->username,
'name' => $this->name,
'email' => $this->email,
];
}
}

Now, when we call the API again, it will have username property in its response:

{
"data": [
{
"id": 8,
"username": "prof.camren.lehner",
"name": "Prof. Camren Lehner",
"email": "[email protected]"
},

... skipped

{
"id": 17,
"username": "miss.susana.crist",
"name": "Miss Susana Crist",
"email": "[email protected]"
}
],
"links": {
"first": "http://localhost:8080/api/v1/users?page=1",
"last": "http://localhost:8080/api/v1/users?page=10",
"prev": null,
"next": "http://localhost:8080/api/v1/users?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"path": "http://localhost:8080/api/v1/users",
"per_page": 10,
"to": 10,
"total": 100
}
}

Most of the times Eloquent's resource classes are enough. But there's time when we need to remove meta and links properties from our JSON response. This must be easy to remove, shouldn't it?

Well, apparently not. They're hard-coded into the response. To remove them, we need to redefine our model's Resource collection class. Create a new class called UserCollection. Back to our terminal, type any of these two artisan commands:

$ php artisan make:resource User --collection
// or
$ php artisan make:resource UserCollection

It should generate UserCollection file located in app/Http/Resources directory with content like below:

class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return parent::toArray($request);
}
}

To remove meta and links property, we need to redefine this UserCollection class's constructor and modify toArray method:

class UserCollection extends ResourceCollection
{
public function __construct($resource)
{
$resource = $resource->getCollection(); // Necessary to remove meta and links
parent::__construct($resource);
}

public function toArray($request)
{
return [
'data' => $this->collection,
];
}
}

Now our response is clean from meta and links:

{
"data": [
{
"id": 8,
"username": "prof.camren.lehner",
"name": "Prof. Camren Lehner",
"email": "[email protected]"
},

... skipped

{
"id": 17,
"username": "miss.susana.crist",
"name": "Miss Susana Crist",
"email": "[email protected]"
}
]

}


Custom Pagination Response

My specific use-case is to remove only links property from the JSON response and add custom pagination property. Here's how my UserCollection class look alike:

class UserCollection extends ResourceCollection
{
private $pagination;

public function __construct($resource)
{
$this->pagination = [
'total' => $resource->total(),
'perPage' => $resource->perPage(),
'currentPage' => $resource->currentPage(),
'from' => $resource->firstItem(),
'to' => $resource->lastItem(),
'lastPage' => $resource->lastPage(),
];

$resource = $resource->getCollection(); // Necessary to remove meta and links

parent::__construct($resource);
}

public function toArray($request)
{
return [
'data' => $this->collection,
'pagination' => $this->pagination,
];
}
}

Now our response looks like this:

{
"data": [
{
"id": 8,
"username": "prof.camren.lehner",
"name": "Prof. Camren Lehner",
"email": "[email protected]"
},

... skipped

{
"id": 17,
"username": "miss.susana.crist",
"name": "Miss Susana Crist",
"email": "[email protected]"
}
],
"pagination": {
"
total": 100,
"perPage": 10,
"currentPage": 1,
"from": 1,
"to": 10,
"lastPage": 10
}
}

Final Words

I hope that you now know how to remove meta and links property from ResourceCollection. If you run into any issues or have any feedback feel free to drop a comment below.

Tags PHP Laravel
Share:

0 comment

Leave a reply

Your email address will not be published. Required fields are marked *