Including extra meta data with a resource response
Tags: laravel, eloquent, apiresource, metadata
Published: 2024-04-22 18:55:21

In the previous [article](https://dev.to/phyothiha/customizing-api-resource-pagination-structure-3ckp), I explained about customizing pagination structure.

Today, I want to show returing a JSON response from the controller method with extra top-level keys along with `data` and `pagination` keys using the resource class.

As you may know, there is also an  organizational standard or preferred format for JSON API responses. I will stick with a pretty basic format.

####Success Response Format

```json
{
    "success": true,
    "statusCode": 200,
    "data": [
        {}, 
        {}
    ],
    "pagination": {
        "current_page": "",
        "last_page": "",
        "per_page": "",
        "total": ""
    }
}
```

A very simple way to return a response from the controller method will be

```php
use App\Http\Resources\UserCollection;
use App\Models\User;

public function index()
{
    return new UserCollection(User::paginate());
}
```

💡[Why use resource collection over resource?](https://laravel.com/docs/10.x/eloquent-resources#resource-collections)

> If you would like to customize the resource collection response, you may create a dedicated resource to represent the collection

As you have read and followed the previous [article](https://dev.to/phyothiha/customizing-api-resource-pagination-structure-3ckp), the return format will be

```json
{
    "data": [
        {}, 
        {}
    ],
    "pagination": {
        "current_page": "",
        "last_page": "",
        "per_page": "",
        "total": ""
    }
}
```

If not, the default structure will return

```json
{
    "data": [],
    "links": {},
    "meta": {}
}
```

So how can we achieve the response format described above?

Well, you might have guessed, but

```php
public function index()
{
    return response()->json([
        'success' => true,
        'statusCode' => 200,
        // how should I use the resource collection class here?
    ], 200);
}
```

Or you might be going the other way around. Create a new resource collection class and add `success` and `statusCode` keys.

####Method #1 ([Adding Meta Data](https://laravel.com/docs/10.x/eloquent-resources#top-level-meta-data))

```php
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    public function toArray(Request $request): array
    {
        return [
            'success' => true,
            'statusCode' => 200,
            'data' => $this->collection,
        ];
    }
}
```

####Method #2 ([Top Level Meta Data](https://laravel.com/docs/10.x/eloquent-resources#top-level-meta-data))

```php
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

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

    public function with(Request $request): array
    {
        return [
            'success' => true,
            'statusCode' => 200,
        ];
    }
}
```

As you see, `success` and `statusCode` sit inside the resource collection class. You already know what kind of approach to use to reduce code duplication.

*A cliffhanger:* What if I want to create a trait and use it in the controller file?

Happy Tinkering ✌️